Live data from Hacker News

An alternative introduction to Rust

words.steveklabnik.com

21–30 of 94 posts

Re: An alternative introduction to Rust

#21
post #3

It definitely feels a little long winded for a person with some background already in systems langauages like C. Do you plan a TLDR for systems language people?

A very short TLDR, in my limited opinion, is basically "Take an ML-ish, make sure everything has C-like performance, while prohibiting all memory safety issues and eliminating aliasing". From those basic principles things you can start reasoning a lot about what Rust must do.

But I agree it does feel a bit weird to need to explain pointers while also assuming people understand memory layouts. There should probably be a quick guide to memory usage, maybe even using C, and from there introduce Rust's concepts on top. It's certainly a hard problem to introduce a high-level, functional, language that also has very powerful low-level concepts.

Thanks so much Steve for doing this work. Reading the guide made it all click into focus for me when I started, and the rest is _mostly_ syntax.

Re: An alternative introduction to Rust

#22
In what sense this introduction is alternative? It's just like every other intro that explains basic and easily understood things about the borrow checker, but doesn't go into details on how you actually live and work with the damned thing. The second thing you do after learning basics is trying to implement some simple data structures, like lists, or even (horror!) double-linked lists. In Rust this is the moment where you start hitting roadblocks, and then you read somewhere that implementing "basic" data structures in Rust isn't a basic exercise at all, and that is kind of discouraging.

Re: An alternative introduction to Rust

#23
I agree with some of the caveats listed by other people here (in general, that this guide seems wishy-washy about what type of programmer it's catering to), but I like the memory layout tables. While I don't remember much about how I thought at the time I might have benefited from such a tutorial myself, when these days I mess around with exploits and the like which do weird things to memory, it often feels surprisingly grounding and illuminating to open up a debugger and start printing the contents of memory, even if on a theoretical basis I already know what it's supposed to look like.

But please make it clear that the tables don't accurately describe the real layout of memory in a compiled Rust program. Heap mappings and thread stacks are typically at random (thanks to ASLR) addresses, rather than the start and end of memory, and the locations of specific heap allocations are usually based on complicated rules depending on the size class of the allocation (differently sized objects never get allocated together in most allocators), thread caches, ordering of buckets within a page, etc. (Some architectures also grow the stack the other way.)

Re: An alternative introduction to Rust

#24
post #22

In what sense this introduction is alternative? It's just like every other intro that explains basic and easily understood things about the borrow checker, but doesn't go into details on how you actually live and work with the damned thing. The second thing you do after learning basics is trying to implement some simple data structures, like lists, or even (horror!) double-linked lists. In Rust this is the moment whe…

This seems like an unfortunate pathological case caused by the abstraction level Rust sits at. The kinds of tree- and graph-like data structures that garbage collected languages can represent in safe code (at the cost of performance) don't work as well in Rust; you can still implement them with various mechanisms (std::swap is very important for trees; Rc and Weak; replacing pointers with indices into a global Vec; etc.), but due to a desire to get optimal low-level performance, core data structures often end up using unsafe blocks in their implementations. The thing is, though, implementing data structures is something of a worst case: in most other code you can use the data structures to provide the pointer relationships you need, but when implementing them you have to do that yourself. Most other code is more naturally amenable to working with the borrow checker - which is not to say it's not difficult.

Re: An alternative introduction to Rust

#25
post #20

I suggest you go with prose that clearer over prose that is more stylistic. For example: Line six has a closing curly brace, and so main, and thus, our program, is over. Could be rewritten as: Line six has a closing curly brace, and so main is over. By extension, our program is over as well. Maybe even with a quick reinforcing of the (hopefully earlier explained) concept that main is the main program block. It's a fi…

I agree. Dedicated tutorial authors of languages with advanced concepts such as Rust, Haskell, etc. really need to take a course or have a quick overview of technical writing. Steve does a pretty good job with Rust, I think. I wish Haskell had good tutorial authors like Steve. Haskell really needs better tutorial authors.

Are CS majors typically required to take a technical writing class like other engineering disciplines?

Re: An alternative introduction to Rust

#26
Steve, really great work, I've appreciated all your efforts as I've played around with Rust as it approaches 1.0. I think this kind of really deep treatment of an important topic belongs somewhere in the introductory docs. I especially like that you give concrete examples of the problems that Rust's concept of ownership solves. The memory diagrams are actually quite helpful (IMHO) regardless of the "direction". Keep up the great work!

Re: An alternative introduction to Rust

#27
I like it, but I would make two suggestions

1) There are many memory schemas for the push_back example, maybe you want to organize them side-by-side with an arrow between them showing which statement caused the change. Saving some vertical space may do some good.

2) I'm not a fan of the sentence structure in many places. Needs more pith. Perhaps apply some Strunk & White and some K&R.

Re: An alternative introduction to Rust

#28
I wonder, for people coming from non-systems programming languages (e.g. Python), whether it would help to visualize what is actually happening under the hood in a scripting language and comparing that to Rust. As others have noted, this guide is written as if to C/C++ programmers, while the intention (I had thought) was to also target scripting language folks?

My experience, having started in C++, then gone to scripting languages, then come back again, is that it can be quite helpful to consider what actually happens under the hood in a scripting language. Because Python's references are more limited, you would never exhibit the same bug that you illustrated in C++, but there are still issues around e.g. aliasing which tend to trip up inexperienced Python programmers, and where you could illustrate interesting things about Rust's ownership model. And boxed/unboxed data types plus reference counting (in Python) would give you an excuse to talk about RAII. So I think that you could do this in a way that would actually speak to savvy scripting programmers, while still being definitively systemsy.

Just a thought.

Re: An alternative introduction to Rust

#29
post #13

It's still too confusing. Try drawing actual pictures to illustrate the scope/lifetime issues. Talking about addresses on the stack is an implementation detail. Things to cover: Basic lifetime concepts in Rust: 1. Scopes are nested. 2. Variable lifetimes are tied to scopes. 3. Unlike other languages, variables can be created tied to a scope outer to the one where they are created. The user can control this by indicat…

   3.  Unlike other languages, variables can be created
       tied to a scope outer to the one where they are
       created. The user can control this by indicating
       that the lifetime of a variable is the same as that
       of some variable from an outer scope. This is Rust's 
       big innovation.
This isn't quite right (or I'm not understanding what you're trying to say).

Given

   let x = 1;
   {
       let y = 1;
   }
there's no way you can make `y` itself live as long as `x`.

   4.  The "=" operator usually means "move", and when it does,
       the right hand side of the "=" becomes inaccessable.
       (This is type-dependent; some types copy when "=" is used.)
       This preserves single ownership.
I think this is "complicating" how =/moves work: it's really binding things by-value that are moves, the = operator isn't special. E.g. `foo(x)` will move `x` into the `foo` call, despite there being no `=` at all.

   2.  You can declare an enum with a data object as a field in a 
       structure. This creates a structure that contains (really links 
       to) another data object.
I don't understand this, could you clarify?

  - The type system really is complex.
I don't think this is very true, what complexity do you see?
Post reply on HN