74 comments

[ 3.3 ms ] story [ 150 ms ] thread
Looks really nicely written and laid out.

One note on borrowing/ownership that really made it click for me was that to move from &mut T to &T you have to transition through owning the value type, so:

&mut T -> T <- &T

Whichever scope holds the actual value-type is the only scope that can make that transition(absent cases like RefMut)

Could you clarify you mean here? Something like this is perfectly valid:

  fn no_mut(a: &mut usize) {
    *a = 10;
    let b: &usize = a;
    println!("a: {}, b: {}", a, b);
  }

  fn main() {
    let mut foo = 42usize;
    no_mut(&mut foo);
  }
If such pointer weakening was not possible, how would you be able to call a method that takes &self on binding of type &mut self? Of course, you can't use a mutably while b is in scope. So, something like the following results in a compiler error:

  fn no_mut(a: &mut usize) {
    let b: &usize = a;
    *a = 10;
    println!("a: {}, b: {}", a, b);
  }
Actually you're right, I didn't realize that the compiler treated a single &mut references like that.

I wonder if what I'm thinking of involved &mut self captures that were happening as part of an impl on a struct. There's definitely some cases there where I was getting tripped up on it.

Ah, now I remember why I tend to use this model:

  use std::thread;

  fn no_mut(a: &mut usize) {
    *a = 10;
    {
        let b: &usize = a;
        println!("a: {}, b: {}", a, b);
    }

    let b: &usize = a;
    thread::spawn(|| {
        println!("b: {}", b);
    });
  }

  fn main() {
    let mut foo = 42usize;
    no_mut(&mut foo);
  }
Similar code but the move throws an error(as it should).

If you don't have the value type then you're constrained by the parent mut lifetime here so it's not just as simple as a conversion that you can then pass around. Otherwise you need to consider all the lifetime scopes which can get a bit unwieldy.

(comment deleted)
If you don't have the value type then you're constrained by the parent mut lifetime here so it's not just as simple as a conversion that you can then pass around.

You cannot move any closure to spawn that captures a non-static reference, since there is no guarantee that the value will live during the lifetime of the thread. (The closure is required to be Send + 'static.) E.g., you can't do (moving to a non-Copy type :)):

  let foo = String::new();

  let t = thread::spawn(|| {
    println!("foo: {}", &foo);
  });
You could move the captures, including foo, but then foo cannot be used in its original scope anymore:

  let foo = String::new();

  let t = thread::spawn(move || {
    println!("foo: {}", &foo);
  });
    
  // This will give an error, because foo is moved.
  println!("{}", foo);
Note that only moving values works, this does not compile (for the same reasons as the first example):

  let foo = String::new();
  let bar = &foo;

  let t = thread::spawn(move || {
    println!("bar: {}", &bar);
  });
(comment deleted)
Downgrading &mut T to &T is perfectly valid in every context[0]. Upgrading from &T to &mut T is impossible in safe Rust and can easily cause undefined behavior when it's done in unsafe block. If you have T, you can create one &mut T reference or many &T references.

[0] Except in a case when there's &mut U reference, which points at some part of the object referenced by &mut T.

Exercises, I want Exercises, no I need Exercises.

In order for me to learn anything, I need some form of "homework". If you want to teach me a new language, a new framework, I need to "get my hands dirty".

Working through exercises makes sure I actually understand what I am reading, and sometimes it even shows me I don't understand what I thought I did.

You could take a look at exercism.io. I just started the exercises on there yesterday so I don't have an informed opinion on whether they are good or not overall, but it might be what you're looking for.

http://exercism.io/languages/rust/about

No, I mean that every chapter ends with exercises testing your knowledge about the chapter's contents.

This is not specific to this github site. I've recently read the O'reilly Programming Rust Book, not a single exercise in it, and the official The Rust Programming Language Book also doesn't have any.

> and the official The Rust Programming Language Book also doesn't have any

Could you expand on bit on what you see as the difference between an "exercise" and the "projects" that the book includes?

- Guessing game: https://doc.rust-lang.org/stable/book/second-edition/ch02-00...

- I/O: https://doc.rust-lang.org/stable/book/second-edition/ch12-00...

- Web server: https://doc.rust-lang.org/stable/book/second-edition/ch20-00...

There's also some exercises scattered at the end of various chapters, but not with the header "exercise"

- Control flow: https://doc.rust-lang.org/stable/book/second-edition/ch03-05...

- Collections: https://doc.rust-lang.org/stable/book/second-edition/ch08-03...

Sometimes they are even inlined with the text:

> Try modifying Cacher to hold a hash map rather than a single value.

> try introducing more generic parameters to increase the flexibility of the Cacher functionality.

- https://doc.rust-lang.org/stable/book/second-edition/ch13-01...

I think this is the difference between the "projects" all through the book and the "exercises" the earlier commenter is looking for: The projects in the Rust book are just a construct to give the example code context. It's not you working through the problem — it's Steve Klabnik, with you just following along. In fact, a reader who is actually learning Rust can't do the projects, because they don't have the requisite knowledge before reading the chapter that the project appears in. "Exercises" are more of a challenge: "Now that you know this stuff, try to accomplish X task on your own." By accomplishing the task, you both prove to yourself that you understood the material and help solidify it in your mind. Retyping code doesn't give the same benefits or experience.

The second list of examples you gave does seem like the right sort of thing. I'm guessing the earlier commenter overlooked those because they're listed under the header "Summary," which kind of screams "skip me."

> In fact, a reader who is actually learning Rust can't do the projects, because they don't have the requisite knowledge before reading the chapter that the project appears in.

Hm, we certainly expect that this is possible. If this is too hard, we need some tuning!

I think maybe I was a little bit imprecise. It's not that the projects are too hard, but that the way the book is structured doesn't give you what you need to complete the project before giving you the project itself. They're a "follow along" thing, not a "here, now you're 100% ready for this" thing. The projects tend to be designed to illustrate the concepts introduced in the chapter, so a reader can't do the project before they've read the chapter, because they don't know the things that the project is meant to teach. And after they've finished the chapter, they've already finished the project just by following along — but they haven't actually demonstrated any mastery of the subject in doing so.

For example, it's not like somebody's going to start TRPL, see "Let's make a guessing game," stop there and successfully make a guessing game — they don't know any Rust at that point! Similarly, IIRC we're not introduced to most of the IO functionality before the IO project, and so on.

Thanks for clarifying. :)

Jake lists both kinds above; it's true that the project chapters are "follow along", but there are also suggestions for doing some extra stuff on your own.

Regardless, I think your overall point is correct: tons of projects is certainly not how we've structured the book. It is a thing some people want and would find useful. We'll see in the future.

Personally, the Rust Book (2nd edition) seems like good teaching material (from the perspective of a junior self-taught JS dev). What would make it even better is adding a few questions at the end of each chapter, much like the homework in https://www.seas.upenn.edu/~cis194/spring13/lectures.html. These don't have to be large projects, but they shouldn't be a simple rehash of the prior code blocks either. Ideally they pose a challenge that, when solved in a "typical beginner way" (whatever that is), cause the reader to stumble over some common gotchas.

The first few chapters actually mention and explain some of those gotchas (like ownership in regards to returning from functions or accepting a reference). The difficulty probably lies in not outright explaining everything, but not making the reader feel completely lost at the same time.

Then again, questions can always be added later on and if the basic reading material is good (which it is!), it's only going to make an already good source even better. I guess that's meant to say thanks for the Rust book.

Makes total sense. Thank you! I’ll give this some thought.
Similarly, what I liked the most about programming MOOCS was the online test/grading server. It gamified the learning, and was very stimulating for me. At one point, all "quantitative" subject learning platform could probably just be a grading server plus exercises.
(comment deleted)
I've always made my own exercises by deciding what I want to build with a language before I build it. Then I break it up into chunks and learn as I go.
I agree. Good exercises will make you realise that you haven't actually read the chapter properly and you should probably go back and actually pay attention!
How about Advent of Code? They start out easy, but after a while the difficulty is all over the place, and it'll force you to seek out new features of the language. It's a somewhat "realistic" way to learn the language, instead of having a set of more contrived set of exercises that only make you look at a particular part of the language.

The first day, for example, will kind of force you to figure out how to parse arguments, how to loop, how to convert strings into ASCII... all basic, practical tools that you will need sooner or later anyway. Now it's your job to pick up a Rust reference, look around for the tools that you need, and use them to solve an actual problem.

That's how I got very comfortable with D.

http://jordi.inversethought.com/blog/advent-of-d/

If you do this for Rust, I'd love to see a blog post like the above.

100% agree with this! I used Advent of Code this year to explore Common Lisp. If you have any programming experience it becomes a fun hunt of "ok, I need to loop over an array. How do I do that in X lang?".
While this probably isn't helpful to you in particular, my company has a learning site geared towards beginner/intermediate programmers, including some content on Rust. The catch: it's in Japanese, so you'll have to use Google translate if you can't read it. The code is in English though.

https://codeprep.jp/books?tags=&sortBy=createdAt&keyword=Rus...

The exercise style is "fill in the blank" so it's not as rigorous for learning, but still fun to get a sense of different language concepts.

I wholeheartedly agree with this! I am a pretty inexperienced self-taught frontend developer currently trying to learn Haskell and C. I went through Learn You A Haskell and have started going through Zed Shaw's Learn C The Hard Way.

On the surface, LYAH looks a lot more polished. It has nice drawings, less typos, seems like an actual book rather than a gathering of notes and thoughts turned into teaching material. But the exercises in LCTHW are amazing. They always challenge my knowledge in a way that often makes me realize that I didn't understand anything from the prior paragraph.

In LYAH I usually tried following along in GHCI to get an intuitive idea of the functions and patterns used. Yet, whenever I sit down to just build something that, while using the same features, deviates from the example code quite a lot, I often notice glaring holes in my understanding of the topics.

And so, bottom line, I want teaching material to ask hard questions which challenge my assumptions and perceived understanding. As a beginner, I can't come up with such questions on my own. Just presenting me with already assembled programs and going through them line by line just doesn't work (for me at least).

Have you taken a look at the Haskell Programming from first principles book? They have a lot of exercises with each chapter.

http://haskellbook.com/

It's an absolutely fantastic book... but you're asking someone to swallow that first chapter on Lambda Calculus. Maybe that's the best approach, but I can see it completely scaring off an entire class (or classes) of programmers.
Thanks for the feedback! It's a good idea to add questions section at the end of each section.
How does this compare to the Rust Programming book?
Programming Rust has 21 chapters and is 583 pages long. I’ve read it, and I’ve also read the online Rust Book (both several times). Most chapters are in the order of 20 to 30 pages long. Programming Rust is one of the best programming books I’ve ever read, and I’ve been coding professionally since 1997. If you want to get an A+ in Rust read Programming Rust a few times. You can see the entire Contents section of the book on Amazon. Below is a list of chapter titles from Programming Rust that get little to zero coverage in this Learning Rust website.

Ownership. References. Expressions. Error Handling. Enums & Patterns. Operator Overloading. Closures. Iterators. Collections. Strings & Text. Input & Output. Concurrency. Macros. Unsafe Code/FFI - the coolest part, they show you how to create a safe wrapper around libgit2.

There are two books with similar titles and I'm under the impression that you don't talk about the one the OP had in mind:

https://www.amazon.com/Rust-Programming-Language-Steve-Klabn...

https://www.amazon.com/Programming-Rust-Fast-Systems-Develop...

I think both are good books, I already have the second one and preordered the first.

(comment deleted)
I assumed he’d misnamed the book, switched the words around, as your first link points out (“The Rust Programming Language”), there isn’t actually a book called “Rust Programming”, and “Programming Rust” seemed like the closest approximation.
My target is preparing a short and sweet way to learn Rust.
I love those succinct introductions to languages, I find it easier to understand when you don't have to read lots of text and languages possibilities are written as a series of quick examples.

What I miss from Rust learning material is a series of exercises that focus on reference, lifetime, ownership where you have to fix some code to make it compile.

For devs, equally familiar in rust and python and ignoring libraries, would you say development speed in both languages is almost the same?
I really don't think that I could code any faster of what I code in rust. Especially if you consider the overall quality of the work.

In my humble opinion python give the impression to move fast, but when you need to maintain the code base the rust compiler is simply too wonderful.

I suspect people probably can do it a bit faster in Python, but like you say, you wouldn't necessarily end up with the same quality of work. The Rust code is likely to be quite fast and very solid, whereas the Python code is likely to be "eh, fast enough" and "stable as long as nobody says the word 'thread' within a 10-block radius."
For me writing Python is fast, until you need to rewrite it when you inevitably refactor. For Python that's an agony, for me.
I'm more familiar with Python than Rust right now, but I feel like after adjusting for amount-I-have-to-look-up-standard-library-things my development speed is similar. The biggest advantage Python gets is IPython.
I write python for most of the day, professionally. I write Rust at home.

I'd say I spend similar time on the same problem with both, maybe a bit more upfront on Rust and a bit more on the tail with Python. This is, of course, disregarding libraries.

Higher dimensional things are trivial in other languages while they are nonobvious in Rust.

For example, this week I was working on a mechanism for one request to start a future and then all further requests for that resource to await that same future.

I implemented it in less than 5 minutes in Node by just storing Promises in a map. But I'm still not sure of the ideal solution in Rust. It's definitely outside of my familiarity zone.

But what I'm finding over the months is that my routine Rust code is pretty fast now once I've run the gauntlet of experiencing the same compiler errors over and over. And when I reach for Rust instead of Node or Python, it takes longer but my executable is 3mb and it's much faster without much additional expense.

Also, it's tough to do async work in an ecosystem that isn't async-everything, something easy to take for granted in Node and Go.

I really want to learn and use Rust, but just lack the motivation, especially when APIs turn out to be incomplete - I think the last one I saw was multicast not allowing me to set the send interface.

I guess the main draw for me to any given language is great libraries with great APIs. Python has those, Javascript has those, C++ has those, Rust... not so much yet.

> I guess the main draw for me to any given language is great libraries with great APIs. Python has those, Javascript has those, C++ has those, Rust... not so much yet.

Well... what makes (especially) Rust libraries great is the relative absence of bugs. I can use a Rust library and have great confidence some ugly bug won't bite me later on. The developers of the libraries you (don't) mention continuously struggle to achieve the same property.

So in a sense those libs are not at all great in the same sense that a Rust library is!

This looks like a fairly nice website. For someone coming from a background of C and D, but familiar with quite a few others, I have to ask: what makes rust different and better? Aside from memory safety, what reason do I have to choose rust over another language?
Did you have another language in mind? Eg Rusts safety means basically nothing if you are comparing it to Python or C#.
Not really, I more meant "in what situations should I choose rust and what makes rust the best choice in that situation instead of _any_ other language."
Python stops you from accidentally sharing mutable state across threads?
Yes. Look up the GIL (Global Interpreter Lock).
Which is why Python doesn't have thread locking... Except, it does.

Perhaps that's because GIL isn't really helpful for preventing logical races? Yet it encourages a false sense of security?

The GIL doesn't stop you from sharing mutable state across threads, nor does it make it generally safe to do so.
Resource safety and expressiveness on level of Python (or close) combined with speed of C.

That said, while I love the idea of Rust I find the language itself offputting somehow. I don't know, maybe I just need to give it another try.

For me it's a love hate thing. I love the way it stops me from doing dumb shit, and really makes you think hard about how to architect properly.

I hate annoying little nitpicky stuff like it won't auto-upcast a u8 to an i32, for example. There should at least be a compiler flag to allow that.

I mostly love it though. The stuff that bothers me is relatively minor and I think will go away as I get more fluent with the language.

How are those different from, say, d, nim, or lisp?
Good (and improving steadily) compiler feedback, centralized package manager, thoughtful approach to language versioning, a syntax that I like (very subjective), and the flexibility to write unsafe code blocks if for some reason you need to. Those are some of my reasons for liking it.
I would add: The most cohesive and supportive large-scale community I have ever seen for a programming language. The Rust team goes to great lengths to maintain a culture of constructive debate and good behavior. As a professional community builder I am in awe of the culture Rust has achieved in its inner circle as well as its extended ecosystem.
I used to know Rust, but I got tired of the churn and went back to Go.
What churn, specifically?

Anything you learned since May 2015 should still be very relevant. That's almost three years ago.

(comment deleted)
Examples or it didn't happen
I trying use rust, but I don't know why sometimes cargo is like hanging to retrieve from github.
If you are going through a proxy server (e.g. at work) then you may find that the SSL interception proxy has not been correctly configured to provide revocation information.
Please file bugs! We'd like to track it down.
It's probably a git/libgit issue. I reported a similar issue(Cloning/Pulling commits from github took forever, Transfer speeds going as low as 1 kbps when my connection was 50mbps).

They asked me to run some commands and log output to measure packet loss/speed etc. and then told me that my connection had 2-5% packet loss which was causing all the problem and I need to talk to my ISP or get a better connection.

I switched my ISP after that and its not a problem anymore.

From the github readme

> I am a Sri Lankan Web Developer who lives in Vietnam. So I am not a native English speaker and just learning Rust

This guide is so well done, props to you. I haven't worked with Rust yet but your docs make it seem so easy to work with.

At that time search was not working, had bit ugly ui, no indicator for current page and etc. Even it's duplicate, this time people actually saw it correctly. So sometimes trying things again is a good thing :) Have a nice weekend!
That was three months ago...

Do you expect people to start participating in that submission with zero comments now that it's three months from the top of the stack?