Readit News logoReadit News
cheepin · 9 years ago
I read through the Rust book, and the problem I was having with it and the other docs is that it was hard to map the Rust concepts with what actually runs when it is compiled. For a language that touts "uncompromising performance", it was difficult for me to find performance characteristics of the underlying abstractions and std library (for example, are algebraic data structures just tagged unions or does the compiler do more fancy things with them? What about iterators?). I'd really like to see a "Rust for C/C++ devs" guide that helps you figure out if you were using [some C++ feature] the way to get that behavior/performance with idiomatic Rust.

Another thing that is still tricky for me is figuring out when I should use 'unsafe' blocks in my code. Is it to be avoided if at all possible, or should I go there any time the 'safe' part of the language is making it difficult to express what I want? The meme that Rust is C++ without SegFaults and or race conditions is a bit misleading since the actual guarantee is that you don't get SegFaults or Race conditions outside of Unsafe blocks, and any nontrivial project will make use of unsafe blocks.

pcwalton · 9 years ago
> for example, are algebraic data structures just tagged unions

They're tagged unions with no implicit heap allocations. I guess we should at least document that in the reference (though we don't want to overspecify, because we do some tricks in the compiler to try to avoid leaving space for the tag if we can). But I don't think it'd be a good idea to document this straight away in the book: the goal is to make Rust easy to pick up, and adding more information than necessary when introducing enums (which a lot of folks will only see for the first time in Rust) isn't going to do people any favors.

> What about iterators?

The documentation for Iter explains this pretty well, I think: https://doc.rust-lang.org/stable/std/iter/

It even shows the exact implementation of (basically) Range, to give you an idea.

That said, it would probably be worth calling out that most iterators are guaranteed not to allocate. Note, though, that that isn't a hard-and-fast constraint that implementors of the trait have to abide by—you can make your own iterators and implement them however efficiently or inefficiently you like.

> The meme that Rust is C++ without SegFaults and or race conditions is a bit misleading since the actual guarantee is that you don't get SegFaults or Race conditions outside of Unsafe blocks, and any nontrivial project will make use of unsafe blocks.

They'll make use of unsafe blocks transitively, by using unsafe code in the standard library or well-tested crates. Think of these unsafe blocks as part of the compiler: you trust the compiler to generate correct machine code when you type "a + b", so likewise you trust the standard library to do the right thing when you say "HashMap::new()".

It is not the case that most projects should use unsafe themselves everywhere: that usually just makes life harder. The primary exception is if you're binding to C code, in which unsafe is unavoidable.

kalkin · 9 years ago
Speaking of "guaranteed not to allocate", is there a way that you could express that in a type? Seems like that might be nice to have.
anuragsoni · 9 years ago
I am not sure if you have come across this "Rust tutorial for c/c++ programmers" https://github.com/nrc/r4cppp but I found it to be nice when I was first exploring Rust (I had prior experience with C++).

I haven't had to resort to "unsafe" blocks in the Rust I have written so far but "ffi" is one use case for unsafe blocks. Another resource that I have yet to read is "https://doc.rust-lang.org/nomicon/" which seems to explain how to write unsafe Rust code.

dikaiosune · 9 years ago
Is there an equivalent guide to the compile-time representation of important constructs for those trying to learn C/C++? I haven't seen anything like that and it seems like most devs in that realm instead rely on experience and tribal knowledge (which is, AFAICT, how it often works in Rust-land right now). I agree it'd be great for Rust to have clearer official docs about some of these things, but it doesn't seem to me like this is readily available for most languages or runtimes.

Re: unsafe, I think that's tough. My personal feeling is that many of Rust's selling points rely on minimizing the use of unsafe (i.e. limiting segfault-relevant portions of the code), and that there are frequently ways to make things work and also make them fast without using unsafe. What's an example where you found yourself thinking about using unsafe instead of a more complex safe construct?

(Somewhat related to this, and especially for anyone reading who might try Rust, I cannot recommend getting on IRC strongly enough. The Rust IRC channels are by and large incredibly friendly and helpful, and for better or worse that's where a lot of the knowledge in the community is currently collected, not as much SO or blogs)

cheepin · 9 years ago
> Is there an equivalent guide to the compile-time representation of important constructs for those trying to learn C/C++?

Definitely. It was taught in school and there's pretty good guides for it online (maybe not caught up to c++11 and beyond, but the fundamentals are there). You're right that it is not readily available for most languages, but when you need to get serious about performance you either are going to have a guide or spend a lot of time looking at assembly/bytecode. To be fair, I'd probably still have to inspect generated code sometimes, but it's nice to have good instincts for how things run to guide your design/implementation so you can spend less time looking at assembly.

http://www.agner.org/optimize/optimizing_cpp.pdf

wyldfire · 9 years ago
> any nontrivial project will make use of unsafe blocks.

Sure! But that's okay. Just don't use 'quantity of unsafe blocks' as a metric of quality and you'll be all set. Think of it like so: don't use it until you have to and try not to have to. For me, that means consulting experts on IRC (etc), "How can I express this goal in idiomatic rust?" No different from learning C/C++ for the first time, IMO. And if no good way exists you may have to use unsafe blocks.

Unsafe blocks aren't bad, just like #pragma-disable-this-warning and --static-checker-I-did-it-this-way-by-design aren't bad. They mean that you've thought critically about the pros and cons and you are going into this decision well aware of the risk. On the flip side they should be the first blocks to closely examine in the face of failures like segfaults/races/etc.

cmrx64 · 9 years ago
> > any nontrivial project will make use of unsafe blocks.

I don't think that's actually true? Most projects make use of no unsafe outside of stdlib and a handful of crates.io crates.

leshow · 9 years ago
Most crates don't make use of unsafe, the stuff that I see that does use unsafe is mostly either embedded applications or stuff like the std lib.

And even if you do use unsafe, you can still use it to build 'safe' abstractions on top of. the idea is that your unsafe code is quarantined and abstracted, and you build on top of it. std::collections is a great example of this.

steveklabnik · 9 years ago
This is an area in which I haven't quite figured out how to communicate properly; I feel like I have a good understanding of how Rust maps to asm, but I don't know how to transfer that understanding to other people.

I'll certainly be reading your link below, thanks for that!

tmzt · 9 years ago
Would an updated and expanded Rust for C++ Programmers make sense as a companion to the book with references to concepts in the book along with low-level details on data structures or implementation? It would nice to see that and Nomicon more closely related and fully up-to-date.

It soulds like an informal "specification" of #[repr(c)] or #[repr(packed)] for common platforms would also be useful for FFI.

ezy · 9 years ago
> it was hard to map the Rust concepts with what actually runs when it is compiled.

This. The primary reason to choose rust is performance -- that is, you want more advanced abstraction/safety capabilities than C++, and you want that with the same or better performance. And performance implies CPU cost and memory usage/layout control. There really isn't any point otherwise.

Therefore, going into at least a little bit of detail on the idioms and performance impact of those idioms is important. Rust is a supposed to be a systems programming language to replace C, do not pretend it's as abstract as ML in the documentation.

What throws me for a loop when learning Rust isn't high level details like the borrow checker or sum types, it's what is happening with cpu & memory[1]. When things are copied, when they aren't, how much do the std derives cost, matching cost, sum type storage cost, etc. Because while the semantics are similar to C++, they are not the same. And you don't have to go nuts specifying it (compilers will differ), but at least give a general understanding/hint of what to do and what to avoid.

To be fair, the doc does have this scattered about, but it doesn't feel a priority (There are many things I've had to search the web for or ask on #rust, or just look at disassembly for).

[1] To take an extremely simple example, RVA is something Rust supposedly does much more consistently than C++, thus returning a new struct by value to be placed wherever is idiomatic. However this isn't called out very clearly (the last time I checked) in the doc, and to a C programmer, it feels very wrong. Stuff like this is extremely important, otherwise we'd just ignore performance and use a JVM based language with the same (or better) abstraction features and a faster compiler. :-)

Manishearth · 9 years ago
> . Is it to be avoided if at all possible, or should I go there any time the 'safe' part of the language is making it difficult to express what I want?

The main reasons to use unsafe code are when you're doing FFI and have to regrettably talk to C/++ libraries, or when designing new abstractions with a safe API boundary. It's tricky to ensure that the former is safe since you eventually have to trust C++ (but then, that's not Rust's fault). It's not hard to ensure that the latter is safe. Looking at a page of code and ensuring that it can't cause segfaults is a much easier task than doing it for the entire codebase.

This is almost all the unsafe code out there. There's a bit of it used for doing manual optimizations. When Rust doesn't let you do what you want, often there are abstractions like RefCell that have a small cost that you can use (and they contribute to the overall safety). In case this happens in performance critical code, you can use unsafe again, but this is very rare.

In Servo, for example, almost all of the unsafe code is of the first two kinds. I've been hacking on Servo for years and didn't write much unsafe code at all -- when I did, it had to do with talking to Spidermonkey, and even that was pretty rare. More recently I'm working on integrating Servo's style system into Firefox (which is C++), and only now have I been regularly writing unsafe code. Even for this project the unsafe code I'm writing abstracts away the inherent unsafety of Firefox's C++ so that others can talk to Firefox with safe Rust code.

But many projects have no unsafe code at all. It's not that common to have unsafe code.

> it was difficult for me to find performance characteristics of the underlying abstractions and std library (for example, are algebraic data structures just tagged unions or does the compiler do more fancy things with them? What about iterators?).

Note that a C++ book won't help here for C++ too. What is a switch compiled down to? Does it use a jump table? :)

But yeah, it would be nice to have a thing for this. I don't think it belongs in the official book, but it should exist :)

ADTs are tagged unions. When non-nullable pointers are involved sometimes the tag is stored as a null pointer (e.g. `Option<Box<Foo>>` is a single pointer, and is None when null. Aside from that, nothing fancy.

Iterators compile down to the equivalent for loops. I can't think of any stdlib iterator which implicitly allocates; they all operate on the stack. In general these are just zero-cost abstractions, they will compile down the the code you would have written with manual loops. This is a recurring theme with the stdlib and even crates from the ecosystem. "extra" costs for abstractions are eschewed in Rust and will often be documented when they exist. So as a rule of thumb assuming that a random abstraction doesn't have an overhead unless explicitly mentioned is good.

adamnemecek · 9 years ago
I would also suggest taking a page out of Apple's playbook and providing some official sample apps like https://developer.apple.com/library/content/navigation/#sect.... Reading the books is one thing, but seeing the patterns actually used is another. You don't need as many as Apple, only a couple really, but make sure they are well written and straddle a couple of use cases. And like go crazy with the idioms, I want to see the most idiomatic Rust code.

When learning a new platform, it's always frustrating having to hunt for good code. I actually find these similarly important as docs (maybe even more because I tend to reference good open source for much longer than docs).

nrjames · 9 years ago
I agree with the example apps. Some annotated source would be great, too. Something similar to the way dc.js annotates this example: https://dc-js.github.io/dc.js/docs/stock.html
dumindunuwan · 9 years ago
+1 for usinf dc.js type examples. I wished many times "Rust by example" could follow this type of detailed explanations and complex examples.
threeseed · 9 years ago
Personally I think Rust should take this one step further. Actually build templates into the platform itself.

For example one for creating a microservice complete with routes, test cases, JSON support etc. Another for a command line application.

In languages with a steeper learning curve like Rust there needs to be more of an opinionated approach to teaching users.

bluejekyll · 9 years ago
I'm not sure how valuable this type of thing really is. Templates tend to fall out of date, since they're not actively used, they're not actively updated to new practices. I've seen this with lots of templates in other languages.

The libraries having excellent documentation and pointing to apps that are similarly implemented tends to be better maintained, IMO.

joshmarlow · 9 years ago
I would love to see Rust with a REPL. I use Python professionally a lot and have done a fair amount of OCaml in my spare time and both have excellent REPls in the form of `ipython` and `coretop`. Quick experiments with auto-complete is incredibly helpful for exploring a language. That's the only thing I really miss from those languages; when I want to wrap my head around a bit of syntax or a library feature in Rust, I build out a quick little experiment and see if it compiles and behaves as I expect it. With a good enough REPL, that's unneeded.
manaskarekar · 9 years ago
Although not exactly a REPL, the rust playground has proven very useful to me for similar purposes. Of course, you need to be online.

https://play.rust-lang.org/

agentgt · 9 years ago
For languages that do not have REPLs I usually just write unit tests.

This works particularly well for Java as the Eclipse compiler iteratively compiles and most IDEs will let you run a single method.

I imagine a similar stopgap could be used for Rust. I know its not the same but in some ways I have sort of disliked REPLs because its is very easy to accidentally delete or loose what you have type and you might as well make your playing around a test (just my 2 cents).

rascul · 9 years ago
Cyph0n · 9 years ago
Scala does this extremely well too. Not sure whether or not a snippet will work? Run 'sbt console' and you're in a REPL with all of your code imported.
joshmarlow · 9 years ago
Something like `cargo shell` or `cargo repl` that automatically imports whatever crate you happen to be working in would be fantastic.

If you had something like that, I imagine you could probably write a Kernel for Jupyter which would be a huge win.

leshow · 9 years ago
coming from haskell too, i missed this. ghci is really fantastic.
bjz_ · 9 years ago
I heard a while back that there was some work going into an interpreter for rust's mid-level IR (MIR), with the intention being to support a REPL. Not sure how that is going though.
tatterdemalion · 9 years ago
The project you're thinking of is called miri, I don't really know the state of it either.

https://github.com/solson/miri

tmzt · 9 years ago
The Dyon[1] language would probably make a good basis for a repl for Rust. It shares many concepts with Rust including a version of ownership.

[1] https://github.com/PistonDevelopers/dyon

You might also be able to link the repl with Rust Language Server which could be linked with incremental compilation, letting you define modules or pub fn's dynamically.

hellofunk · 9 years ago
I assume you mean OCaml's "utop" ?
joshmarlow · 9 years ago
Technically yes. "utop" is the extended repl, but "coretop" is "utop" except it all ready has Jane Street Core loaded up.
dikaiosune · 9 years ago
It's important to note that this is an RFC which has been proposed, and there's likely to be a good deal of discussion and revision before it's merged/adopted as the official 2017 roadmap.

The conversation can be followed/joined/whatever here: https://github.com/rust-lang/rfcs/pull/1774

collinmanderson · 9 years ago
"accordance with RFC 1728" - could they have chosen a naming scheme so their documents are not confused with the _real_ RFC's? Even RRFC 1728 would helpful. Or maybe just #1728?
tatterdemalion · 9 years ago
Lexical scope. You should assume an RFC cited in a Rust RFC is a Rust RFC, you're in the Rust RFC scope. If an IETF RFC is cited in a Rust RFC, it won't be ambiguous.
Can_Not · 9 years ago
Why do "the _real_ RFC's" have exclusive rights to that term?
leshow · 9 years ago
Awesome. I have used Iron a few times to write small web services, but I can't wait for Rust to really have a strong story for the backend. If that happens it'll be the first language I reach for whenever I need to write a backend.

I think it has a lot of great bonuses already. It's language ergonomics are that of a high-level language, yet it is extremely fast, and I can be very confident in my code if it compiles.

Rust is one of my favorite languages, keep up the great work guys.

vvanders · 9 years ago
Yup, happy to see everything on the list.

If one thing more than any stands out it's Rust's commitment not just to building a language but building an incredible community. With how seriously the release processes are being taken to the way new people are welcomed. Serious kudos, I know it's not the most technically engaging work but it makes a huge difference.

sjellis · 9 years ago
Yes, as far I can tell, Rust is probably (pun intended) the gold standard in these areas. I only looked at Rust briefly, because the language itself felt too complex for my simple needs, but I was hugely impressed by how much concern and effort the core team seem to put into every aspect of the developer experience. The only other group that I know with that level of focus is the .NET people at Microsoft.
berntb · 9 years ago
Are you saying that Rust, a system programming language, can compete with the scripting languages in speed of developing features?!

Or are you saying that it is a pleasure to use, so you'll use it for smaller backends where development speed isn't that critical?

(Asking, not flaming. :-) )

tatterdemalion · 9 years ago
> Are you saying that Rust, a system programming language, can compete with the scripting languages in speed of developing features?!

I'll say it. At work, the backend is Rails, and I am a Rust contributor in my freetime. I am in the early stages of working on a framework for web apps in Rust & I believe it will be comparatively productive to Rails. Only your code will be faster and many bugs will be caught at compile time.

leshow · 9 years ago
Absolutely. But the trade-off is not so simple. I can be fairly confident that if my code compiles there are far fewer bugs than if I had written it in nodejs or php. So while it may take longer to get to the initial point that I have something running, I save time on subsequent refactors.

And the added bonus, is that my code runs 10-20x faster. So I really didn't give up anything to get the increased confidence.

However, I have to backtrack a bit here, because the largest Rust backend I've written was probably a little less than 10k lines. So while it was non-trivial it wasn't a massive undertaking.

pjmlp · 9 years ago
It is possible to have both capabilities in a programming la language.

Dead Comment

dumindunuwan · 9 years ago
Other than that, if we had some tool inside Rust ecosystem to support server side rendering for frontend, Rust will be the ultimate language of web.
fixxer · 9 years ago
Awesome to see the learning curve addressed with such high priority.

I like Rust and I'd like to use it more, but I generally lean on Go or C for writing anything that needs performance. I can't quite get past the awkward, fumbling stage with Rust. Go, on the other hand, was really easy to get acquainted with and not too substantial of an effort to get to strong expertise. I've been able to teach Go to junior devs with no background and hand off projects within a couple weeks. Rust is awesome, but fits in a very different bracket IMO.

pcwalton · 9 years ago
It's important to note that Go and C have very different design goals from Rust. Go was never designed to have zero-cost abstractions (garbage collection being the most obvious outcome of this, but there are many others), and it has a runtime. C was never designed for safety and security, memory safety or otherwise. In short, Go sacrifices performance and C sacrifices safety, while Rust's goal is to sacrifice neither.

Addressing the learning curve of Rust is important, but we aren't going to be able to do it by adopting concepts from Go or C. By and large, they just don't apply.

yazaddaruvala · 9 years ago
What are your thought on making `rustc` poly-lingual?

Ideally, all libraries (i.e. should be written by experts) are written in Rust, but applications are allowed to be written in RustScript.

RustScript would be optimized for lower learning curve. example[0]: - No `unsafe` allowed. - Everything is implicitly an `Arc<_>`. - All numerics are BigNum. - etc.

This is inspired by the popularity of using Rust within other languages, like Ruby. The way this would differ from using another language: All the Rust tooling would be the same. Realistically it would just be a different parser for the Rust AST. Therefore no memory layout issues, or FFI involved. Like syntax-sugar to the extreme, the compiler (except the parser) wouldn't even know the difference.

[0] I'm just listing simplifications, regardless of if they are a good idea.

kjksf · 9 years ago
It's also important to note that Go was designed for programmer productivity and Rust wasn't.

GC is incredible productivity boost which is why no recent language (except Rust) does manual memory management.

Compile times in Go are a fraction of Rust compile times, which is another productivity boost.

Go gives you one good way to do concurrency, Rust believes in tyranny of choice.

Without mentioning that you don't paint the whole picture, just the parts that are favorable to Rust.

cbHXBY1D · 9 years ago
If syntax isn't going to be changed, is that really addressing the learning curve of the language?

Edit: I'm going to answer my own question here: yes. I just sometimes think Rust is a victim of its own success when people expect to learn Rust quickly because they learned Python in two days.

No one expects to master C++ in a weekend.

dysfunctor · 9 years ago
Go outperforms rust on all kinds of benchmarks, has a larger community, better documentation, more third party libraries, and significantly better tooling.

What's the value proposition for using rust over go?

cm3 · 9 years ago
The hard part doesn't go away with unless you pull in a GC or something similar to take care of lifetime bugs. In Go you always use a GC and circumvent the explicit lifetime management syntax of Rust. Some data structures are very hard to write without something akin to a GC, so my bets are on a few opcodes trickling down into mainstream cpus making GC easier to implement in optimal time and space. I'm surprised Android hasn't forced anything like that in their supported ARM designs, since such cpu support has been available in production systems in the 1970s and hence isn't anything revolutionary, just not on the radar like vector instructions have been.
dikaiosune · 9 years ago
Is this based on your experience learning lifetimes in Rust? I very rarely find myself needing to do convoluted lifetime tricks -- most of the code I write doesn't even need explicit annotations. So I'd be curious to hear what project you may have worked on as a beginner where lifetime management because a serious obstacle.
Cyph0n · 9 years ago
Could you provide references for the claim that hardware support for GCs had been in CPUs for decades?
cm3 · 9 years ago
> Rust should integrate easily with C++ code

The day that Rust manages to have always up to date Qt bindings that do not force you to make compromises compared to the C++ API, I think the C++ support will be at a comfortable level. Right now there are fresh efforts in the Rust and Haskell camps to solve this cleanly in a modern way. It would certainly help if the consumption of C++ APIs via llvm (which is used a lot byt Rust) was made a first class feature like you can import and export C APIs. Exporting C++ classes is a whole different story and may not map in any reasonable way to Rust modules or crates.

bch · 9 years ago
I'm ignorant of Rusts ABI/requirements, but can the C ABI be used as a lingua franca, or are there necessary facilities that are unsupportable there?
dikaiosune · 9 years ago
FFI through a C ABI is how Rust <-> C++ currently works, but IIUC it's quite limiting when one might want to make use of C++ specific features. Especially important when a given C++ project doesn't have a fully-featured C API, or any C API at all.
whyever · 9 years ago
There is no general C++ ABI, the ABI depends on the compiler and the standard library.
rjammala · 9 years ago
One way to improve productivity of Rust with respect to the learning curve is to add more screencasts/tutorials to http://intorust.com

I found the existing ones very helpful and instructive.

dj-wonk · 9 years ago
Thanks, I'm watching now. I recommend it.

"The primary author ... and the narrator on the screencasts, is Nicholas Matsakis ... Niko has been involved in Rust since 2011 and is a member of the Rust core team as well as the leader of the language and compiler teams"