Taking a wild guess here, but it sounds like you maybe referring to issues addressed by Non-Lexical Lifetimes (NLL)?
Reference: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll....
NLL are a part of Rust 2018 Edition.
Three complementary books are the best resources:
- The Official book: https://doc.rust-lang.org/book/
- The Rust By Example book : https://doc.rust-lang.org/rust-by-example/
- Programming Rust (O'Reilly) : https://www.amazon.com/Programming-Rust-Fast-Systems-Develop...
Edit: removed outdated behaviour of migration mode.
If that were true, then this example would fail to compile, since it fails with the old AST borrowck: https://play.rust-lang.org/?version=stable&mode=debug&editio...
See: https://rust-lang-nursery.github.io/edition-guide/rust-2018/...
The transition mode is for Rust 2015 code.
In edition 2018, migration mode is turned on.
I learned myself about this today btw, after I saw this PR: https://github.com/rust-lang/rust/pull/58342
I think I was mistaken about one point though which is that migration mode is erroring if one of the two errors. IIRC migration mode was introduced that way but it seems to have been changed to be a bit more tolerant than AST borrowck.
Anyways, more NLL fun is to come, and it's to come to both editions.
You can completely take advantage of any NLL feature, you just might be able to write code that should be an error but is instead a warning if you hit an edge case (I think this would be considered a bug in one of the borrow checkers since NLL is supposed to allow anything that the old borrow checker allows).
Of course the big distinction is that Rust mandates it. There's lots of C code out there that happens to work fine with shared data structures that never collide in practice (or at least never collide under non-hostile input...) - see for instance every standard libc API that returns a pointer to a static buffer. Our codebase merely had a style guide, and lots of older code was less disciplined. Rust forces you to care up front about everything.
Isn't it just “one mutator at a time”?
>Is there a K&R equivalent that an experienced programmer can get pick up to get productive with the language soon?
(Opinion incoming.) The Rust Book[1] is great iff you are a complete beginner. If you are an experienced programmer, who knows his way around concepts like resource management and ownership, it's kind of a drag. Rust by Example[2] is much better. The Nomicon[3] is interesting, but it's mostly about unsafe.
[1] https://doc.rust-lang.org/book/
Here's my Rust advice for C and C++ programmers:
- Rust is a higher-level language than C. A C/C++ programmer could think of Rust as "C++ without most of the footguns and magic."
- Certain types of C/C++ code will translate very easily to Rust. For example, if your code mostly transforms bytes (or data structures) into other bytes (or data structures), then Rust will usually be fairly easy to learn. We could call this "mostly functional" C code, with only localized mutability, and with clear, hierarchical data structures. Examples: Most typical Unix CLI tools.
- Certain kinds of C and C++ will translate very badly to Rust. If you have a big web of mutable objects, all of which point to each other and update each other, then your first experience of Rust will probably be frustrating. Examples: doubly-linked lists, traditional GUIs, typical video games. You can do all these things in Rust, but you'll need to either re-architect them or use more advanced features. (See http://cglab.ca/~abeinges/blah/too-many-lists/book/ for doubly-linked lists, or https://kyren.github.io/2018/09/14/rustconf-talk.html for video games.)
- Async Rust is not ready for prime-time. We make limited use of async Rust at work. It's rock-solid and powerful, but it's missing critical ergonomic features and it demands a surprisingly high level of Rust knowledge. See https://areweasyncyet.rs/.
Two good Rust books are https://doc.rust-lang.org/stable/book/ and http://shop.oreilly.com/product/0636920040385.do. "The Rust Programming Language" seems to work best for people coming from Ruby or JavaScript, but I've known several C/C++ programmers who preferred the O'Reilly book.
Honestly, if you're happy with C, there's no reason to switch to Rust. (Except, maybe, preventing exploits, if you worry about that.) If, however, you love certain parts of C++ and hate other parts of C++, then Rust might be worth a look. Anyway, that's my personal take. :-) Overall, I've been really enjoying Rust. It generates fast, reliable code and it fits the way I think.
1. Lots of little CLI tools, statically linked using https://github.com/emk/rust-musl-builder. These are fast, portable, easy to share, and easy to add to Docker containers. For a fun open source example, see https://github.com/faradayio/geochunk, which groups US zip codes into evenly-sized chunks.
2. Code where we need to handle all the corner cases very carefully. Rust's enum and match are wonderful for this. An older open source example would be https://github.com/faradayio/cage, which performed all sorts of fiddly transformations on docker-compose.yml files. (I need to massively overhaul this to work with https://kustomize.io/ someday.)
3. Code which moves around large amounts of data, and maybe processes some of it. This might involve REST APIs, AMQP queues, cloud buckets or databases. Sometimes we wind up writing a little extra glue code, but we're pretty happy overall.
This morning, I'm working on an unreleased open source command-line tool that moves large database tables between different local and cloud databases. This actually uses async Rust (specifically https://tokio.rs/blog/2018-08-async-await/), which is definitely bleeding edge. But this particular code benefits enormously from Tokio, so we're taking the plunge.
Overall, our Rust code is fast and reliable. I enjoy working on it, and my boss likes the fact that our Rust code tends to be very solid.
Now at https://www.prisma.io/ we're converting our Scala codebase one module at a time to Rust, plugging them to the Scala codebase with JNA until all the code is converted. Plan is to have better portability between different languages and smaller resource usage. With Rust, interfacing other languages such as Java/Scala, Javascript and so on is quite ergonomic.
I also saw Kraken cryptocurrency exchange looking for Rust developers to help with transition, so it seems there is some work opportunities already in the field.
Rust is not for good c/c++ programmer. It is for those who is not familiar with c/c++ but have some knowledge with functional programming.
As a C++ programmer, you can try golang instead of for productive
Then came what I thought should be a simple task; since my code was mostly recursive, I wanted to add and remove from a map containing the program's current binding state, so when the evaluator sees a 'let' block:
(let ((a 1) (b 2))
(+ a b))
for instance, it evaluates the addition with a Map like: {'a':1, 'b':2}, and once that's finished evaluating, the evaluator returns from that scope and we're back to having nothing bound. After all, I don't want to access 'a' and 'b' outside my let.As it turns out, Rust doesn't support using maps (or hash maps) in this way. You need to allocate and borrow them, and you can't borrow them in multiple places, so I couldn't have a function that checks whether something is bound, since I'm already borrowing the map in my evaluator function.
I was left asking: why can I do this in C (or another 'low level' language, passing the bindings as a pointer to array of a k-v struct that I simply swap with another and remember to free()) and do it in Python (or another 'high level' language like Haskell, creating the map anonymously when calling eval recursively), but not in Rust? The language seems to be somewhat focused on ideas of immutability, but I can't do the things that immutability lets me.
Other things seemed to get in the way too. Once you've 'match'ed a variable you can't actually deal with the thing you matched, because you've already borrowed it when you did the matching. In Haskell (case statement) this is no problem at all:
is_cons e =
case (car e) of
Nothing -> False
Just _ -> case (cdr e) of -- still matching on e
Nothing -> False
Just d -> ...
Maybe I had the wrong use case for Rust, or I was too stupid to figure things out. Either way, I'm a little happier having decided to literally learn Haskell instead, which turned out to be easier than dealing with Rust, a language which is supposed to be more like languages I was already familiar with (C/C++/imperative).Your HashMap issues may have been solved by the Entry API.