Hacker News new | ask | show | jobs
by eknkc 3424 days ago
Just curious, I really want to like Rust but take a look at the State API documentation for managed state feature: https://api.rocket.rs/rocket/struct.State.html (screenshot: http://c.ekin.io/3c2q112x1p0y)

Is this readable to Rust people? I mean, can you look at this and say, "ah ok, I'm gonna call this and that then I'll have the state" directly?

I'm lost but I have zero Rust knowledge so this is a sincere question, does this mess make sense when you get into it?

15 comments

It is readable, but you are right it is terribly formatted with a lot of not-very-important information in huge fonts.

I think rustdoc needs quite a lot of work in general. For example it doesn't even give a list of methods at the start of each type's page. Want to know which methods you can call on a `String`? Enjoy scrolling...

https://doc.rust-lang.org/std/string/struct.String.html

> I think rustdoc needs quite a lot of work in general.

It does. Honestly, it's quite hard to contribute to at the moment. This is going to improve in the very near future; there's a PR in the queue that's the start of the ability to start making it easier. I hope to make it vastly so someday in the future. Always so much work to do...

The +/- button will do that for you. It's one of the first things I do once I read the top example.
Wait, that thing is a button? I never knew that. I guess you can tell because when you hover over it, the status bar on your browser says "javascript:void(0)". I feel like this bit of design might just be a little bit too flat.
We've discussed flipping the defaults; it was decided before I started writing so many docs and examples. Very different today!
Maybe you could add a responsive right bar with the list of methods, visible when the screen is large enough. My 24'' monitor has 30% wasted space right now.
Yes, something like this would be very useful too.
Ah I never noticed that. Yeah that is quite nice but I expect 99% of other people don't notice it either.

I definitely think the defaults should have everything except the description at the top collapsed.

The docs make sense once you get used to them and understand what they're telling you, but it does take some getting used to. The general output of rustdoc could also be improved in my opinion.

A bit more summary of available methods/trait impls somewhere would be nice.

I'd appreciate a three scrollable pane setup, first pane similar to whats already there on the left, but always visible. Second pane type, usage, examples, methods, impls. Third pane in the middle, widest, actual information in long form. Inline examples of each method are incredibly helpful and the std library docs have quite a few of those but not always. Its sometimes hard to understand how to use a method or type or impl depending on its signature.

Panes should scroll+highlight currently viewed items in the actual doc (third) pane.

I find rustdoc's default layout to be suboptimal. Javadocs[0] give you the method summary table right below the prose and they are screen-filling like wikipedia, so the prose does not take up too much space.

With rustdoc you have to click on the [-] in the top right to get an overview of the available methods.

But yes, once I have that overview I can usually pick out the methods I need. The type signatures can be a little complex, but so are C++ templates.

[0] http://download.java.net/java/jdk9/docs/api/java/util/Option...

The first time I went on a Rust doc page I felt exactly like you: «what the hell is this mess ! I understand nothing».

But a few weeks in, it started to make total sense, and now I see the page you link to and I'm like «That's pretty clear, no problem here». It just takes a little time to get used to the documentation syntax and formatting I guess.

Given the description of State, the fact that it only has two methods to get at the inner value (.inner() and Deref::deref()), and each returns a different lifetime (one is 'r which is longer than or equal to the lifetime of the State, the other the lifetime of the State), it should be reasonably obvious to people who've coded Rust for a while. The example helps, obviously.
With a couple of weeks of Rust experience, that seems pretty clear to me, but the State type isn't the whole explanation. Check https://api.rocket.rs/rocket/struct.Rocket.html#method.manag... too.
I'm not a rust guy, don't know it at all... and to me it's not too much different than interface/type definitions for the .Net framework in C#.

It's often easier to work from examples though, but I do know that you often see interesting ways to do things when you look at API docs.

OT: the framework looks interesting... routing as attributes is pretty cool, would be nice if one of the examples on the main page used a route variable though. I am curious how this compares in terms of requests/second of hello world vs. alternates... I would imagine the memory overhead would be much lower, but curious on throughput for the underlying model.

There shouldn't be methods without examples in any documentation.

Unfortunately Rust is not as revolutionary in this regard as in others :/ but other languages/ecosystems/tools are just as bad :(

My initial instinct is to ignore all of that documentation in your screenshot.

Specifically, the first thing, inner(), says that you generally don't have to call it because there's a Deref implementation. Deref is a trait that lets you implement things that loosely resemble smart pointers or similar wrapper types: for instance, CString, which tracks a Rust-owned C-compatible string (null-terminated), has a Deref implementation to an array of bytes. So I know that I can usually use a State<T> when a function seems likely to want an &T or Box<T> or similar, and I can carry on and not care very much more until I need to.

The rest are trait implementations of common traits (Debug is like Python's repr, PartialEq and Eq are comparisons, etc.), and the documentation is from the trait. I think this is a rustdoc weakness, but I know about it, so I can ignore reading the docs.

The documentation is not easy to read, and it often lacks important descriptive context about how to use a library. I started learning Rust about a month ago, and I feel like the documentation has made my life more difficult than it needed to.
Yeah, it's reasonably understandable.

In fact it's a pretty awesome example of Rust's traits in practice since it requires Sync + Send so you know it needs to be thread safe(and the type system will enforce it).

It is, but I think people accept that these are automatically generated outputs from compiler-created code.

Like any notation, once you understand how to break it apart and you learn what symbols mean, it becomes easier to interpret large fragments like this.

One pretty significant issue for newcomers is that rustdoc emphasises traits, rather than methods. Sometimes there is more indirections. It takes more insider knowledge to know that fmt() is actually called by the println!() macro, so you're unlikely to encounter that method unless you're digging into the internals.

The font sizes are dubious, as it is drawing more attention to type signatures than the actual function name and description. Once you draw your eye to the right place it seems pretty reasonable to me.
The "traits" feature of Rust's type system provides a lot of nice polymorphism and general ergonomics, but one consequence of its existence is that you see a lot of trait-related noise in the docs and it's maybe emphasized more than it should be by the styling.

If you know Rust, it's pretty easy to cut through it if you know what you're looking for, and sometimes it's actually useful.

One thing I've noticed is that the answer to "how do I use this library?" is often hidden away in a sub-page about one of the traits it defines.

Many libraries are made of boring top-level code and then interesting trait implementations. Structuring the documentation like the code doesn't work out very well in that case.

I think that out of all the bad things about Haskell that may or may not be reflected in Rust, this is one that annoys me the most: a lot of libraries have very strange interfaces that they do a poor job of explaining, often seemingly enabled by fancy uses of the type system. A recent example I ran into is formatted reading/writing of date/time objects in the `chrono` crate, which seems to be the blessed option for all I can find on Google. Anyway, just getting the bare minimum functionality that I could use in other languages by calling e.g. `strftime("%Y-%m-%d")` required researching a bunch of interlocking types and traits scattered across the crate, documentation nearly or entirely absent, and resulted in some pretty ugly code to boot.

I expect that the interface works this way in an attempt to avoid parsing format strings at run time ("zero cost abstractions" and all that), and that's great, but the lack of documentation made it pretty miserable to use, and I would classify my Rust skills as "intermediate". I expect a beginner would have just given up (and taken to HN to complain about the learning curve).

This is something I've seen, but does it apply to chrono? I'm looking at its README on GitHub (https://github.com/chronotope/chrono), and useful examples are right there up front.

DateTime::format seems to do the same thing as strftime, with a format string parsed at run-time.

I wonder if it would be useful if the docs offered a "what functions should my type have" hint for trait-heavy functions. That way all the required functions are in the same place.

Paging steveklabnik, what do you think?

What exactly do you mean by this? Could you provide an example?

Personally I think some big gains in documentation clarity could be made by sorting the methods differently, possibly more compactly; I remember when I was first starting with Rust it was easy to overlook trait impls, e.g. a useful `Deref<[T]>` implementation because they tend to show up further down in the docs.

I might also have benefited from a clearer overview of all the core traits in one place, especially the ones having to do with taking references. IIRC `Deref`, `Borrow`, and `AsRef` are all different traits and the differences between them (and how to idiomatically use them in common patterns) are not totally clear. But maybe I just skipped a chapter of "the book" or something.

Im so tired of people who dont know rust complaining about rust. Learn rust and then complain. And yes it makes perfect sense ... if you know rust.
Once you understand traits, those trait bounds really aren't bad. Now if this were some macro-heavy library, I could understand the complaints, but this is just constraining the type of the generic type.

I find it readable, it's saying that the "inner" function returns a reference to the value the State object is containing (which must be of a type that implements Send and Sync), and that reference cannot outlive the State object the value was returned from.

There are many languages I don't/didn't have to learn before I could read and/or patch code written in it. I hacked on C and C++ code long before I understood their basics. Go would've been the same if I hadn't bothered to spend a couple days learning it shortly after first exposure.