Rust’s documentation is about to drastically improve
words.steveklabnik.com
words.steveklabnik.com
There should be a list of somewhat larger projects (similar to the sample apps for Cocoa https://developer.apple.com/library/mac/navigation/index.htm...) maintained by people who actually understand the language. For me, and I imagine a lot of other people, the hardest part about learning a new language/platform is getting from the stage where I understand the syntax and APIs to getting somewhat proficient with it and being able to make informed decisions about how things should be done in that language.
A lot of times, when I look at some open source projects to learn from, I'm left with the impression that the author might not have really understood what s/he's doing and that really increases my frustration with the platform. A list of canonical projects would prevent this.
I'm aware of Servo but I feel that Servo is a.) too large of a project for a Rust n00b to learn from b.) it's not always up to date WRT to the language version and the best practices.
Alternatively, this could also be a list of 3rd party projects blessed by the Rust people as good projects to learn from.
While it might seem like a waste of time, I feel like this would e.g. reduce the number of people needing help on IRC or the mailing list so it might actually save time.
Agreed, and I plan on explicitly tackling this too. That'll come after Cargo is a bit more solid, however.
(That is, Rust borrows concepts from functional languages, but is not a deeply functional language itself.)
But yes, as they develop, I'll be encouraging the use of idioms directly in the documentation. My years of Ruby make me a big believer in developing and following idioms.
Oh, one last thing about that: iterators are way better than explicit loops in Rust, because loops have to do bounds checking, but iterators don't. So generally, iterators are not just better stylistically, but also performance-wise too.
They still have to check something to know when to stop iterating, though, don't they? You may have traded a bounds check for a dynamic dispatch or some "is done" check, but there's still some conditional logic each iteration isn't there?
So when you you loop over an array, your loop conditional makes sure that your index hasn't indexed out of bounds, in addition to the bounds checking that is performed when actually indexing the array. So you in a sense pay a double price for the same assurance. (This is modulo compiler optimizations.)
Rust has to guarantee memory safety (I guess Java makes the same promise). This means that you have to have bounds checking for array indexing, lest you index out of bounds of some array and get killed by the operating system, if that memory happens to be outside of your process' "turf". You can't eliminate that in general (or; it's hecka hard), but you can probably encapsulate things like iterating over data structures like arrays, vet the code, and say that "this thing loops from 0 to the length of the array minus 1... I swear on my mother's future grave that it is safe to turn off bounds checking for array indexing here." (The way they do it in Rust may be more rigorous than this, for all I know!)
The hard part about doing that is that it's only safe if the array is guaranteed not to be mutated during the loop. Rust enforces this through its borrow checking system.
The iteration protocol is just a trait:
trait Iterator<A> {
fn next(&mut self) -> Option<A>;
}
That is, "an iterator" is an object that has a next method yielding an optional value, with a missing value indicating the end of iteration. This is conventionally used statically dispatched, and the next method will normally be inlined, so the compiler can optimise it well.(In particular iterators over simple data structures like vectors optimise to the same code as the equivalent in C/C++, modulo one small bug where LLVM doesn't yet fully understand the nonnullability of Rust's references.)
Imagine we want to print out every single element of a `Vec`, Rust's growable array type. Here's the code with a loop:
fn main() {
let v = vec!(1, 2, 3);
for i in range(0, v.len()) {
println!("Number {}", v.get(i));
}
}
This of course, has to check that it's only iterated the maximum number of times. The check I'm referring to, though, is in `v.get`. That has to do a bounds check on the array. If we use the iterator version... fn main() {
let v = vec!(1, 2, 3);
for i in v.iter() {
println!("Number {}", i);
}
}
Now we get each element out of the vector. No more bounds check!I think one of the sources of success for Golang is its "hit the ground running" approach which takes you from zero to hacker in a short amount of time. Rust is considerably more advanced than Go, but there's no reason that it can't adopt a similar attitude of pragmatism and real-world applicability (although its libraries might lag behind Go's). Having first-rate documentation is a huge step in that direction and a very promising development.
Agreed! One of the weird things about Rust is that it's been open source since the beginning, where languages like Go and Swift have been closed for years before having their first release be very polished.
Rust will get there. Like most things, it just takes time and sweat.
Furthermore, saying that Rust has been worked on "since 2006" is misleading. From then until 2009 it was just the work of one man idly tinkering in his free time, hardly a serious project.
Barriers for committing to Rust itself are very low. Also, they aggressively moderate their spaces according to their CoC. A few days ago, I asked a rather picky question on their subreddit and was quite surprised how on-point and serious the answers were. Given that the topic had the potential for some trolling, it was surprisingly calm.
It's really a community I am happy in.
Edit: I got a bit excited. Obviously, the point of the whole thing is: Mozilla investing into Rust docs seriously and Cargo really shows that this is not an lab language anymore.
I'm working on my first non-trivial system with Rust right now, and I'm finding that the learning curve related to the borrow checker and lifetimes is rough. I'd liken it to macros in Common Lisp, but not quite as a cliff as monads.
In other words, I would like to ask that a substantial amount of your time in documentation at some point be pointed at the lifetime & memory system, as it is, IMO, the really unusual and hard part of Rust (As well as the whole freaking point of it too! ;)).
Others entirely differ. And that's A-OK! :)
I also suspect that lifetimes are one of those features that people might say, "I learned Rust, and I don't code in it, but learning about lifetimes improved my code in $DAYJOB_LANGUAGE." Just like how I think Haskell improved my ability to program in a variety of other languages, but I don't really write Haskell anymore.
As an aside, what does this mean for your position at Balanced?
I elaborated here: http://words.steveklabnik.com/sf
Nothing puts me off from a language or system quicker than clicking through to a tutorial that is either (a) extensive but 2-3 versions out of date or (b) hopelessly cursory ("here's 2 pages of neat stuff, see you later").
I plan on having examples built-in with the documentation for everything, but actually approved by the team, rather than just as comments. They'll be much higher quality that way.
It also forces documentation to be up-to-date; one of the reasons I selected Go over Rust a year ago (besides more mature libraries and better documentation) was the fact that Rust seemed to be rapidly changing.
> Rust seemed to be rapidly changing.
Yup. That's what happens with a pre-1.0 language. :)
I wish you the best luck with the new rust documentation and have well placed high expectations for what you will likely do with it.
Yes, Rust is 100% open source, so anyone can submit such things.
And thank you!
I guess I like the bite sized chunks and the organization by concepts.
Although, I never know when there is more info about the current section under the fold.
I hope thats helpful.
Sounds like a good approach, in general.