New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
first draft of 'ownership' #58
Conversation
|
|
||
| Before we get to the details, two important notes about the ownership system. | ||
| Rust’s central feature is called ‘ownership’. It is a feature that is | ||
| straightforward to explain, but has deep impleications for the rest of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: impleications -> implications
6c6b601
to
3164bf5
Compare
ddd1ae6
to
f1b9e52
Compare
|
Read it and thought it was excellent. One question I had, which I already mentioned to @steveklabnik on IRC, was whether it makes sense to introduce moves first as shallow copies and then lead up to the errors that would result if you didn't have moves (but oh we do!), or whether it's better to first describe it as a move, and then show why a move makes sense. I'm not really sure. |
|
I agree with @nikomatsakis that this is really good work! I have some detailed notes below -- the biggest wording issue is around confusion with the term "copying" (not always clear when you mean deep and when shallow). From a high-level perspective, I think you're hitting almost all the right notes here, with one exception: you're not emphasizing enough that Rust is statically checking ownership for you. This should be more of a running theme, and I think it's worth noting that this is a major innovation in Rust that allows it to provide memory safety without garbage collection, amongst numerous other advantages that we'll see later in the book. Ownership
Instead: Rust is committed to both safety and speed. One of the key tools for
Instead: This can happen because the programmer isn't used to thinking Variable binding scope
Did you mean: string literal? Memory and allocation
Instead: Languages without a garbage collector often force you to call a second I like the point about RAII. We should use the book to standardize on
This needs to say shallowly copied and be very emphatic about it, Also, you first mention shallow copying, then take a digression on the Definitely worth dwelling on these points. Clone
Say: deeply copy. For this section, important to be crystal clear each Copy
A better way to say this is: In other words, there's no difference between deep and shallow copying
How about: any group of simple scalar values can be Copy, but nothing that Ownership and functionsThis is good, and quite clear. But I think you should also take this opportunity to re-emphasize the static checking point. I would suggest that, with the example with |
These aren't the best, but they're a start.
|
I pushed up a commit which takes care of all of this feedback, except maybe the extra emphasis on compile-time checks. Gonna think more carefully about when to do this. I don't want to do it too much either. |
|
|
||
| The double colon (`::`) is a kind of scope operator, allowing us to namespace this | ||
| particular `from()` function under the `String` type itself, rather than using | ||
| some sort of name like `string_from()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This explanation feels very out of place. Perhaps we should cover that before getting here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We haven't yet talked about anything related to this, and forcing all of the materials about modules to be this early in the book would be a bummer. I do dislike forward references though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if String::from is self explanatory enough to hand wave away?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly appreciated this note @steveklabnik, having not worked in Rust for a while but having passing familiarity it felt like it was a worthy aside to me. It gave just enough I was no longer curious and ended up googling another doc, and it isn't overly-distracting.
Addendum: I come from Ruby-land originally, so :: in another language always catches my eye. So there is definitely a bias to my thought process
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this be simplified to something similar to:
The double colon (
::) indicates we are using a function from a specific module. In this case we use thefrom()method located inside theStringmodule. That is the only thing you need to know for know, we will talk about modules in length a little bit later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@azerupi That actually makes it a bit more clear than the current text, I like it a lot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit of misinformation, as it's not getting it out of the String module at all, but calling a static method on the String type (as the current text notes). Maybe it's a small enough lie, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appealing to constructors may be useful for those who are familiar with the notion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stood out to me too. Too much kinda/sorta. Maybe "Calls from function of the String type"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit of misinformation, as it's not getting it out of the String module at all, but calling a static method on the String type
Indeed, I realized my mistake after posting it. We should avoid misinformation even for the sake of simplification. It could end up exploding back into our face.
The double colon (::) indicates we are using a function that is located inside a module or associated with a type. In this case we use the
from()method associated to theStringtype. That is the only thing you need to know for know, we will talk about modules and functions associated to types (traits forward reference?) in length a little bit later.
Is "functions associated to / with types" semantically correct? I wanted to find something visually simple to understand instead of bringing up the traits jargon.
|
Some various thoughts about this:
|
|
Thanks @sgrif! I chose
I think this ties into @aturon's comments above about compile-time checking. Need to motivate this better, for sure.
Ah, interesting. Hmmmmmmmm..... I like this idea. |
|
FWIW tying it into function calling could also help out with the explanation of |
| [Variable bindings][bindings] have a property in Rust: they ‘have ownership’ | ||
| of what they’re bound to. This means that when a binding goes out of scope, | ||
| Rust will free the bound resources. For example: | ||
| For this, Rust has a second string type, `String`. You can create a `String` from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd make it clear that the first type is &str here, instead of relying on the user to have recognised that from the error message - they might see it, assume the &str is scary and unrelated and not have that immediately cleared up for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, this is a good point. I'm being a bit evasive here because we haven't seen the & symbol at all, and it's explained in the very next section. But that it appears in an error message might be a good reason for a forward reference.
|
https://twitter.com/maskoficarus/status/687422424225296385 <- maybe I should list some standard types which are Copy. |
|
The error around |
|
As means of motivation, it might be worth talking about how this is not reference counting, and why. (This might be good for one of those "this is advanced, don't worry about it" sections) |
|
Hello! Based on a quick interaction with you on Twitter, @steveklabnik, I read this chapter. Here's a couple of thoughts and my responses to questions posed there, coming at this as someone with a couple of decades of programming experience, but zero Rust exposure. Before getting to that though: This chapter makes me want to read the next one. :) It's really well-written and makes Rust intriguing. If I weren't such a heavy front-end person right now, I'd be all like "NEED TO TRY THIS RIGHT NOW". Thank you for your work here! Quality documentation is the BEST! Thoughts on OwnershipIf one can describes a part of the learning curve as "fighting with" the language semantics, and it states that people will continue to fight with it over time, it makes the language sound fairly unappealing and difficult, and already makes me feel nervous about trying anything with the language. I like the bit of encouragement at the end of that paragraph, though. :) This feeling didn't persist, but feels worth noting. The second example changes from The idea of Move vs Clone is interesting, but feels rather foreign and distinct within Rust. I feel like I understand the reasons behind it, now, but I didn't after my first pass. I think it clarified when writing my answers below. To answer the two questions posed on Twitter: Does this make any sense to me?Yes, it makes sense to me. :) The technical details are quite clear. The code examples are simple, concise, and the detailed versions with comments are great. I also like the memory diagrams. I understand that when I assign a variable to another variable, if it is not marked as Do I have a sense of why this feature is valuable?Originally, I wrote "No, I do not" but the truth is that I think I do understand the reason, but I don't feel like I really understand the full value right now, with just this chapter. There is a line that says "Remember: If we tried to use I can understand that Ownership is the answer to the balance between safety and speed -- I think. It keeps me safe in the sense that I don't have to think about things like Explicitly stating the above reason (assuming I got the right reason) would be of some value in this chapter, I think. It's there in a sense, in the section discussing being at a crossroads, and I pulled it out after a bit more review, but it feels like it'd be a nice summary at the end of a section. That way, it could more clearly tie the decisions behind Ownership back to the safety / speed balance as introduced at the beginning of the chapter. Final ThoughtsI do feel like I've read it and it all makes sense, but I feel like some of the clarity I got was because I was trying to answer the above questions. Without those guiding questions, I'm not sure I'd have really seen this value or understood the decision behind Ownership. I really enjoyed reading it, and as this solidifies, I really want to read the book in full now. :) Thank you again for your efforts here! It's awesome. :) |
|
This is an excellent chapter! As what I replied on Twitter, mentioning "shallow copy" really help people with Python / Ruby background understand what is going on. For C++ guys, the "move" semantics may sound more straightforward, though. There's one more thing that seems unclear to me: Here |
|
This is great! I'm just getting in to Rust, and documentation like this is making it really fun! One thing that I found a little confusing was near the end of the section on Also, nits: I just noticed two places in the last paragraph of that section where you don't have Thanks for the work you're putting in to this; I look forward to reading the next chapters! :) |
| checker’, where the Rust compiler refuses to compile a program that the author | ||
| thinks is valid. This can happen because the programmer isn’t used to thinking | ||
| carefully about ownership, or is thinking about it differently from the way | ||
| that Rust does. You probably will experience similar things at first. There is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"experience something similar at first"?
| There’s a problem here! Both `data` pointers are pointing to the same place. | ||
| Why is this a problem? Well, when `s2` goes out of scope, it will free the | ||
| memory that `data` points to. And then `s1` goes out of scope, and it will | ||
| _also_ try to free the memory that `data` points to! That’s bad. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's bad long before s1 goes out of scope! Actually it's bad before either do!
Big Picture
Will the subsequent sections be reinforcing that ownership is actually a larger thing, and useful for more than memory management? (iterator/view invalidation, use-after-close, data races, sequencing!) Medium Picture
|
Smooth out a sentence.
You don't just fight it less, you deeply thank him for pointing your mistakes ! :)
Immutability is not the problem here. This works fine. The problem is that &str doesn't implement the “Add” trait. Mixing the concepts of mutability with where the values are allocated could be quite misleading for beginners imho. |
|
@athaeryn Thanks!
Yes, it's the way it's normally used. |
|
@brianarn thanks! If you check out the other PRs, you can in fact read the next two sections.... they're just even less polished than this one is |
|
Thank you everyone for your feedback! There's still some tweaking I want to do with this, in particular, highlighting why this matters more, but I'm going to do that in another PR. Thanks so much! |
first draft of 'ownership'
Proofread ch03-01
r? @aturon
Rendered: https://github.com/rust-lang/book/blob/ownership/src/ownership.md
I should add the diagrams before we merge this. EDIT: diagrams added