We actually had someone say that the new version is so much better than the old book, even though it's incomplete, that it's like a medical trial where the treatment is going so well it'd be unethical to keep people on the placebo. A bit hyperbolic, yes, but so is "this doesn't help anybody".
Although I have some years of practice in programming, I always prefer to learn new languages using some kind of practical tutorial that introduces the topics as we go along. I've just finished the guessing_game tutorial and really understood the general idea of cargo, externs, associated functions, etc.
Congratulations, and I hope that the rest of the book is as practical on introducing the following concepts as the tutorial was for me..
They're example driven, but most aren't as large as the Guessing Game is for the most part; the I/O project chapter is, and we'll probably have one more near the end of the book as well.
I found the new version significantly better than the old. I immediately 'got it' after reading some of the new chapters compared to the more complete old version which I sometimes struggled with for a while.
I would definitely recommend this to rust beginners, and tell them to just use the old book where the new isn't complete.
14 out of 20 chapters have at least a draft, so this is still useful, even if it's not complete. I generally tell people to start here and then go read the old book afterwards to get the stuff that's not there yet, if they have the energy.
I had tried running Rust for a few months now, but it didn't really clicked until I went through this book.
Thanks to the great explanations of the concepts of rust, the helpful exercises and examples, I have not only since been able to contribute to the RustLang, but also am in the process of a PR for Servo, created a website using rocket.rs, and started using Rust at work.
It's definitely true that the initial hump of learning Rust was more intense than other languages such as Python, but this book helped to alleviate a lot of the initial pain.
I'm reading the section on ownership. Valgrind usually thinks my 'modern C++' code is leak free, and when it complains I understand why, so I'm not a complete stranger to systems programming. But for whatever reason I have always run into a brick wall with rusts strange compiler messages regarding lifetimes.
I read the previous books bit on ownership. I'm not sure if this new version is better written or I've come across this stuff so many times that it's starting to make sense to me through pure attrition - but the picture does seem clearer to me. Particularly the "Ownership and Functions" bit.
I'll definitely make use of this next time I think I have a rust shaped problem. Whether that will put me over the edge into being a rust user will remain to be seen (I have my reservations about lots of other stuff), but I appreciate they're really trying with the documentation side of things.
As a C++ programmer, I understand ownership and borrowing, but I find the lifetime syntax impenetrable. It clutters the code with annotations that seem like they could be deduced by the compiler.
For example, a variable's lifetime is relative to another variable or function. Why must we create a placeholder name like 'a instead of referring to the other variable by name? Take this example from section 10.3:
Why couldn't we write it as something like the following?
fn longest(x: &str, y: &str) -> &'x str {
x
}
Or instead of requiring lifetimes everywhere, the compiler could use conservative defaults but allow optional lifetime annotations to reduce the lifetime if needed or to release memory sooner. For example, in this struct from section 10.3, why is 'a necessary when config is a non-mut reference and thus must outlive a struct App instance? There is a Rust issue filed for this: https://github.com/rust-lang/rfcs/issues/1532
The Rust community prefers explicitness in many cases. We already have lifetime elision for simpler things. Both of these cases in your comment have been extensively discussed and decided against.
The reason why the former is not done is because it makes the signature dependent on the body. This means that changing some code could potentially change the signature of the function, which is the kind of silent magic that folks would prefer to be explicit. Also, as the function gets larger, this is harder to deduce by looking at the code. The current elision rules all operate on the signature, so you only need to look at the signature to figure out the lifetimes, elision or not.
The latter is way more controversial. The reason there is similar; folks want it to be obvious from the type name that it is a borrowing type, and changes to the internals shouldn't magically change the signature without an explicit acknowledgement.
Even type arg lifetime elision was controversial. Currently, in Rust, you can write a function like `fn foo(x: &u8) -> Foo`, where `Foo` is actually `Foo<'a>`, and the compiler inserts the lifetimes in the right places. When this was proposed there was a good chance that it would not happen (though as you can see it did happen). So the status quo on lifetime elision is probably not going to change in my opinion, given how hard it was to make the last one happen (of course, you have the "overton window" of acceptable implicitness gradually shifting due to that change, so it might after all)
To me personally, this explicitness is a minor annoyance when dealing with simpler stuff, but is invaluable in codebases making heavier use of lifetimes, like rustc (which avoids reference counting, even though compilers generally need a lot of tricky sharing). And ultimately, I appreciate it even in codebases with fewer lifetimes; I don't like having to peek at a function's code to understand how it's supposed to be used.
No lifetime parameters can be shorter than the lifetime of the struct itself, and that's part of the so-called WF (well-formed(ness)) rules in Rust (which the compiler tries to make as implicit as possible).
However, that has nothing to do with why you have to have a parameter. The parameter is there to make all instances of App track the actual lifetime, e.g. you can tell between App<'foo> and App<'static> (and in the former case, it can keep the borrow that made the &'foo Config alive for as long as the App<'foo> sticks around, and if this is longer than the underlying data lives for, you get an "use after free" error).
Combined with function signatures, Rust can track complex interactions without ever looking at callee bodies, and if you're never reusing a lifetime parameter, you get just as much flexibility as if you were passing the references around directly.
This is something that the C++ attempts at tracking scopes and enforcing a set of rules about them, don't seem to have figure out yet. You need a certain amount of annotations to keep the correct mapping, otherwise you just lose information and have to assume every struct that contains a reference may borrow everything that was borrowed at some point and the borrow may have "escaped" into a struct.
You're either too conservative and thus can't apply the rules to prevent iterator invalidation and data races like Rust can with borrows (Cyclone didn't have borrow-checking either IIRC), or you're ignoring an entire subset of UAF bugs waiting to happen.
Even for the purpose of preventing UAF, such an imprecise aliasing-analysis-like conservative system may be too restricting for many real-world usecases, whereas Rust's, ironically, wouldn't be.
I thought the same thing (especially about structs), but after some time with Rust I actually like the explicitness about lifetime rules.
As soon as you are not fighting with lifetimes anymore, it's just a bit more to type. IMHO it actually makes code easier to read, since I don't have to remember a lot of weird rules.
But I have to admit that Rust already has some rules for lifetime elision (e.g. `fn getx(&self) -> &T { &self.x }`. I can only speak for myself but IMHO these rules have a pretty good cost/benefit ratio. For me introducing more rules adds just more cost for diminishing value.
> For example, a variable's lifetime is relative to another variable or function. Why must we create a placeholder name like 'a instead of referring to the other variable by name?
Because they're different namespaces? &'x refers to the lifetime x, which has no relation to the local variable x, the global x, the type x or the module x.
Reading that, and the little blurb about move and copy semantics below the infographic, it occurred to me that borrowing is actually rather easily described as real like sharing (which is unfortunately already a loaded term in much of CS due to multiprocessing).
When you share something that is not copyable (such as a pen), you give it to the person borrowing it until they return it when done.
When you share something that is copyable (and idea, some software, a joke), you give someone their own copy to do with as they please. There is no return required.
Borrowing, which is from the receiver's perspective, implies returning, while sharing, from the sender's perspective, may or not mat imply a later return of something.
I wonder how much the conceptual baggage of the terminology affects how people learn them.
Okay, that's really cool and does probably the best job I've seen of an overview of &mut and &.
I feel like you could almost build a rust cheat-sheet poster out of this and few other useful syntax visualizations(traits, generic + lifetime syntax, etc).
And to be clear, 10.3 is just the intro; we have a full chapter later with the complicated stuff.
We decided to do it this way so that you can write real Rust code without going "what is that syntax"; you don't need to have a full understanding of the more exotic aspects of lifetimes to write useful code in Rust.
I've just been through this section. I'd love a separate tutorial just for the borrowing lifetimes and error handling that make rust different.
It's to easy to go though the current tutorial and think "wow, this is easy and makes sense" only to come completely undone when you try to do something.
Sigh. Looks like it's time for round 5 of time to learn Rust(my personal failing, not meant as a slight against the language at all). Has the pace of sweeping changes to the language slowed down in the past year?
I rode the Ember train from 1.4 to now and it was an extremely ehausting process to get to 2.0 with nearly every version requiring frustrating architectural rewrites. The upgrade from 2.0 to 2.8 took like 15 minutes and didn't require a single major refactor. I'm not trying to switch context away from a discussion of Rust, that's just for example purposes of stabilizing.
I found myself struggling to find guides that still worked as written and I was looking at guides because I failed to become competent from the Rust book and Rust by example alone so I wasn't able to diagnose the upgrade path for the content. This has stopped my learning dead in its tracks every time.
To be clear, I have no CS background or functional programming experience so I'm not the target audience and I don't mean any this as a slight against the language.
I started trying to learn Rust at 0.7 (maybe a bit earlier, I can only find references to 0.7 in a few projects of mine). Boy howdy did that feel like an exercise in futility. I would set it aside for 3 weeks, revisit it, and find entire language constructs had been removed. I complained about this and Steve Klabnik graciously reminded me that it was a work in progress and that the work was being done out in the open intentionally. I really can't thank him enough for that since it caused me to go from frustrated to sympathetic. As a result I decided to not write the language off. And I'm glad I didn't. After things slowed down around the betas for 1.0 it became clear that Rust was worth learning. I haven't had a chance to use it professionally, but for personal projects I find myself reaching for Rust for problems that would have caused me to have reached for C in the past.
Also, Google has gotten significantly better about returning current and up to date information on Rust as well. Around 2013-2014 my biggest gripe was that I'd search for how to do something only to find advice that was woefully out of date. I haven't had that experience in well over a year now.
I started to write a VM in Rust and every weekend, when I managed to get some time for work it would usually no longer work and the reason for it had to be found in some mailing list or commit message.
I had to stop doing that and rewrote it in C.
'Fortunately' we had some other problems as well but Im still hopeful that Rust is the language you want to use for this in the future.
I think it is. Especially if you keep your code in a public repo, any breaking changes (probably just tweaks as opposed to huge features that break stuff), will probably have a pr filed via cargo.
From what I understand, the rust team has scripts that crawls the repos and compiles everything looking for usages of some feature being used that's going to break in the next release, and they will issue a pull request to fix those.
It's more subtle than that. For most things, we guarantee no breakage at all, and we do runs like that (though not against github, but against crates.io) to verify we haven't accidentally broken something.
For stuff that we are allowed to change, but might cause breakage, we will try to find stuff and send PRs.
But the default and our intention is zero breakage as much as possible, not just "we'll fix it for you". We'd guarantee absolutely none but it's not actually possible in a statically typed language, so we have to go with "effectively none."
It's been, god, 3 years now since I've started writing large Golang applications and I've yet to look back on a project ~6 months later without noticing flaws in design/architecture/intuitiveness. You are not alone in your hurdles.
On the bright side, that's am easy way to measure your growth. Look at it this way, if in six months or more if you look back on code you're writing now that's non-trivial and you can't think of a single thing you would do different what's more likely, that you were lucky/good enough to design it perfectly, or that you didn't actually learn anything from the experience (even if it's what assumptions about projects in that industry you shouldn't make going forward)?
I dread the day I no longer see progress. I suspect it's also about the time I'll really find programming no longer fun.
In my very limited experience, the libraries still aren't stable. I ran into a bunch of errors a couple of days ago because my distro was on 1.14 rust compiler but the latest was 1.15. I'm not sure exactly what the issue is but it looked like the standard libraries had changed between versions.
1.15 contained a new feature that was seriously awaited, so a lot of libraries pushed out a new version using that feature. Even with that, though, Cargo _should_ have saved you here, via the lockfile.
It shouldn't have been the standard library though. If it was, that'd be a serious bug! If you do figure it out, and it is the standard library, please file a bug. And if you need any help, feel free to reach out. I'm here to help.
This was using the latest toml and serde releases, which I think does use that new attribute stuff (which is fucking cool btw). But no warning from cargo until it was compiling the dependencies.
Yeah, that makes sense, they would totally be using it.
Still, upgrading to those releases _should_ have taken manual intervention; how were you depending on them in your Cargo.toml? And I guess you had no Cargo.lock for some reason?
Brand new project. I added them by putting the dependencies into the cargo.toml file (with the current version), is that how you're meant to add them or is there some kind of "cargo install" command?
Ah ha! Yeah, so it makes sense that the latest version would need the latest version of the compiler. You could use the previous version and it should still work. Usually, when a project requires a new Rust version, there's a bump to whichever version determines compatibility. (for x.y.z, x if x != and y if x == 0) Given that you said it was breaking, I thought you meant you had a project that suddenly stopped working, my bad.
For now, that's the standard way, at some point, we might pull a "cargo add" command into core, but there's some blocking on parsing.
This book has been hugely helpful for me to get started in Rust. I've been following since the original "Rust for Rubyists" from Steve Klabnik.
Steve if you are listening, thanks for putting all the hard work into the original book, the revision as The Rust Programming Language, and this most recent revision.
Thanks to you both! And very seriously, this edition could not have happened without carols10cents. I am exceedingly grateful to have her as a co-author. While the original book was largely me, this edition is very much indebted to her work.
Was drawn to the "An I/O Project" section. Everyone learns differently, and I like to learn by example, that's why I often scroll to the bottom of the man page to see example before reading the description of a new command.
So I'd like to see more stuff like that. Anyone know of a good Rust "Cookbook"? I found a few but there were just started with only a few examples.
Also in my case, I can breeze through the start section pretty quickly, I understand the ownership basics, traits and generics separately. But seeing structs, traits, lifetimes and generic together it feels like hitting a wall. I'd welcome a resource that sort of uses lots of examples with combinations of those things.
I just replied above with a similar comment. I also learn better by following a practical example like the "guessing_game" tutorial.
Didn't read the rest of the book, so I don't know if there are more tutorials, but I learn better with that because it clearly shows what one can do with the language.
I have found this book to be an excellent resource. Also I have been supplementing it with the oreilly book "Programming Rust" (early release at this point) which has also been great.
http://shop.oreilly.com/product/0636920040385.do
I have had very little experience with C style languages in the past and am mostly scripting until recently.
Both carols10cents and I, the primary authors, are reading this thread. Happy to answer any questions other than "when will it be done," as estimations are hard ;)
Yes we are! There's someone working on Vietnamese [1]. It's a bit blocked on mdbook support [2], but the translation part could start before that's done. Chapters 2, 3, 4, and 6 are effectively "frozen" for print at this point [3] so they'd be the place I'd recommend starting first!
I'm currently starting to learn rust (previous java and go developer). But at the moment it feels like the good old times where I was developing with an editor and api doc side by side.
What is the current editor of choice for rust projects?
I tried intellij-rust and atom with the racer plugin. Both seem to be in a somewhat early stage of development regarding the auto completion.
Regarding the book: I like it. Has been a long time since I had fun reading such a book. With most languages I just learn by googeling one problem after another until it clicks ;)
IDE integration is a big theme of this year, so this will change rapidly over the next few months. We aim to provide plugins for everything, pretty much. Specifically, we're implementing Microsoft's "Language Server" interface, so anything that can interface with it will work well, http://langserver.org/ has the full list, I believe.
The new revision of the book is using mdbook, which hasn't yet implemented playground support [1].
An RFC has recently been accepted to start the infrastructure of featuring the new book (and other resources) on doc.rust-lang.org/book, but the implementation isn't done yet. Soon!
Which rustup command is that? I could only find "doc" which opens the documentation in a browser, which is not much help if you've got no internet.
Ah... I see. You have to run "rustup component list" and it'll print out a whole bunch of things that you can install like cargo and rustc and 44 different versions of std and also somewhere in there the docs. And then you have to know that that the thing you have to pass to "rustup component add" is not the string you get out of "rustup component list" (something like "rust-docs-armv7-unknown-linux-gnueabihf") but in fact just "rust-docs". And none of this seems documented anywhere in the help text in rustup itself, at least not the 1.0.0 version that I have.
Hey carols10cents and/or steveklabnik, what project was the example code in the Performance section (13.4) taken from? I'm interested in Rust and audio and especially both of them combined.
Something I'm curious about is why this next iteration of the Rust Programming Language book has been developed relatively hidden away from new folks, who have to continue using the old book unless they stumble upon the new one somehow.
I would think that if the content of the new book does a better job at educating new users of the language, you would want that to be in front of everybody as absolutely soon as possible.
With that in mind, why is the strategy to complete the new book entirely before moving over? If the new one has such big gaps that it can't stand on its own, why not try some gradual migration?
We talk about it quite a bit on IRC, on Twitter, in the forums/Reddit, and elsewhere. I've specifically put the text out in front of new people to get feedback.
> why is the strategy to complete the new book entirely before moving over?
This is not _strictly speaking_ true, but it's been blocked on some other things. We haven't been able to use mdBook, the tool we use for the new book, inside the Rust repository until two days ago[1]. This was due to a number of factors that had nothing to do with the book.
Soon[2], we'll be able to actually present both books on the website, and so this will be messaged a bit better.
> If the new one has such big gaps that it can't stand on its own,
Well, I mean, we started from scratch. The full first draft isn't even done yet! When's the right time for this, after one chapter is done? Two? Five? It's a tough question, but the actual nuts and bolts of the build process made that question moot, and now that it's 75% done by chapter count, it's all just kind of working out.
> why this next iteration of the Rust Programming Language book has been developed relatively hidden away from new folks, who have to continue using the old book unless they stumble upon the new one somehow
As a technical documentation nerd, I hope we can get a rudimentary JS (or WASM) IDE and compiler worked out and A/B test everything on Khan Academy for version 3.0. One impossible task at a time : )
I've been reading the early access version for a while now, and it is excellent. I hadn't had much luck with the "official" documentation, previously.
Jim Blandy's writing is an exemplar for good teaching technique, and this book is shaping up to be the go-to recommendation for learning Rust, in my opinion.
I have been reading it as well. For my taste, it is a bit too verbose.
I like to see something along the lines of the K&R book or the GoPL book. I was hoping that "Programming Rust" is such a book, but I was disappointed. And (may be it is just me) I like to see exercises in Programming books.
C an Go are pretty concise languages so they lend themselves to K&R and GoPL. Rust is a big language (like C++) and is still changing quite a bit so I don't think you'll get a similar tome in the near future. (imo)
https://rust-lang.github.io/book/ch17-00-oop.html
This doesn't help anybody. Continue to use the rust book at:
https://doc.rust-lang.org/doc/stable/book/