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)
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.
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.
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);
});
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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."
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?
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."
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.
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.
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.
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!
74 comments
[ 3.3 ms ] story [ 150 ms ] threadOne 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)
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.
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.
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 :)):
You could move the captures, including foo, but then foo cannot be used in its original scope anymore: Note that only moving values works, this does not compile (for the same reasons as the first example):[0] Except in a case when there's &mut U reference, which points at some part of the object referenced by &mut T.
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.
http://exercism.io/languages/rust/about
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.
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...
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."
Hm, we certainly expect that this is possible. If this is too hard, we need some tuning!
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.
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.
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.
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.
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.
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).
http://haskellbook.com/
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.
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.
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.
> Small exercises to get you used to reading and writing Rust code. Includes practice reading and responding to compiler messages!
https://github.com/carols10cents/rustlings
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'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.
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 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!
Perhaps that's because GIL isn't really helpful for preventing logical races? Yet it encourages a false sense of security?
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.
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.
Anything you learned since May 2015 should still be very relevant. That's almost three years ago.
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.
> 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.
https://news.ycombinator.com/item?id=16048065
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?