10 ms·
An Intern's Experience with Rust
- ncmncm 7y agoThat is also not how you would write it in idiomatic C++. The "before" example is C, or bad C++. You are allowed to write bad C++, as you are allowed to write bad Rust. But if you are to compare langues honestly, you should be comparing good code in one language to good code in the other. The alternative is tendentious but typical, and nothing to be proud of.
- thrower123 7y agoI wouldn't expect an intern to write idiomatic modern C++. That looked to me to about what I would expect from a university student that had passing familiarity with C++ from their coursework; there is still an unbelievable amount of "C-with-classes" in active use and pedogogy kicking around.
- pjmlp 7y agoGiven how we used to teach C++ to university first year students back in 1994 - 2000, it still confuses me that there are so bad teachers keeping "C-with-classes" in active use. Basically, even without the STL, the students would get our department C++ library with the usual stuff (strings, arrays, vectors, bounds checking enabled), and the teaching would be similar to the way that Kate Gregory preaches how to teach modern C++.
- echelon 7y agoI found the article quite reasonable. The author explained that Rust tought them RAII and how they should have been writing C/++. Rust seems anecdotally better at onboarding new engineers than C/++. We're going to start seeing more articles like this.
- Thaxll 7y ago"Rust code is wonderful to write and read" Writing I'm not sure, reading it's just awful, everytime someone show his project on HN I check github and I'm baffled how the code looks bad as a human reader. (){}<>''-_
- CDSlice 7y agoIs it really that much worse than C or JS? Most popular languages other than Python use () and {}, <> are just for generics like many other languages, " is used for strings, - is just a minus sign, and _ is just used when you need to ignore something when matching just like it is used in Python. Yes, Rust is a very symbol rich language, but it also is very information dense which makes it easier to read than many other languages once you learn it.
- Crinus 7y agoInformation density isn't the end goal though, otherwise we'd all be writing into something like APL or its derivatives (K/Q/J/etc). And yeah, if you have ever missed a & in C++ you can easily see why a single character symbol can be annoying (i really prefer C#'s approach where you not only use ref and out in function declarations, but also during function calls - though overall i prefer Pascal's more explicit and verbose syntax).
- derefr 7y agoI think the goal programming languages optimize for is somewhere between, on the one hand, "learnability" / "time to fluency"; and, on the other, "power/expressivity when fluent." When you multiply these measures together, gives you an area measured in "productivity over time of each man-hour invested into the project by population of developers of various stages of fluency with the language" (where for an average developer on the project, any given man-hour is partially spent writing code, and partially spent becoming more fluent in the language.) APL-likes (and Forth-likes, and Lisps when you use the macro features) are a bit too far on the "power when fluent" axis, at the expense of learnability, and so the total area of the product is small. Might be good for one-man projects, but not for large ones. Minimal languages like ASM or Java, where there are just a few primitives and everything else is design patterns, trade high "learnability" for low "power when fluent", and so also have a reduced optimization product. Most languages aim somewhere in the middle, though often with a bias toward the side where they think the optimum might truly lie; for example, Go is slightly on the "learnable" side, and Rust is slightly on the "power when fluent" side, but both seem to be generally more productive per average-programmer-man-hour invested into FOSS projects than languages that more heavily favour just one axis. (Side-note: I'd love to see some real numbers crunched on this. A comparison of rival FOSS projects to implement some shared standard in different languages would make for a pretty good "natural experiment" to look at productivity over. First thing that springs to mind for me personally are the rival Ethereum clients of Geth (= Go) and Parity (= Rust), but I'm sure you can think of your own examples.)
- echelon 7y ago> First lesson: Rust isn’t as hard as I expected We're going to see a lot more of this. As the language has matured, the Rust folks have paid great attention to easing the learning curve. Even with the borrow checker, it's not that far from Java or a scripting language these days. Most people won't hit lifetimes early on in their use.
- derefr 7y ago> Most people won't hit lifetimes early on in their use. Depends on what you're doing, doesn't it? If you're using Rust for its original design-goal purpose—as a systems language—then you're probably writing some kind of daemon that keeps persistent in-memory state between RPC requests from clients; or some kind of UNIX-ish CLI tool that reduces over IO streams. And as soon as a request, or a stream event, wants to persist some state into a longer-lived scope, lifetimes rear their head.
- echelon 7y agoA junior programmer isn't going to encounter this unless they're trying really hard. Someone with the knowledge of how to write code like this is already familiar with the problem domain and the vocabulary. They'll know enough to be able to find out how to get this performance out of Rust. New programmers aren't going to look for this or need it right off the bat. They'll still be able to leverage a modern, safe language with lots of features and an extremely compelling package manager.
- dakom 7y agoOr on a more basic level - trying to store a ref in a struct. There's plenty of ways to not do that or think about the problem in other ways, but I think it's fairly easy to accidentally run into that problem early on.
- jandrese 7y agoI don't know. I recently took a Rust course and our day three project was to build a simple multi-threaded webserver. The really easy kind in C where you accept a connection and then spawn a thread to handle the request so the main thread can get back to accepting new connections ASAP. This turned out to be quite challenging in Rust, even when starting from a working single threaded server. Threading the needle on borrows was quite a challenge.
- thelazydogsback 7y agoAlthough object lifetime and borrowing is mentioned, he focuses on the pattern expression which he's likely to get in any modern language. Rust has many great qualities and I've been looking to find a project for it, but it just doesn't seem like the model for long-running processes with immutable data-structures and complex/dynamic/interlinked lifetimes. Seems like dev. effort is better spent on functionality than managing lifetimes, especially given that modern GC is so fast. (And I've seen C++ ports to C# become faster, due to unneeded calling of copy c'tors, and other goodness.) I can totally see the case for Rust in systems code where lifetime is gated by a system/API call and you want to safely pass buffers around during the duration of the call, for inner-loop gaming, for embedded, etc. But seeing it's en vogue, there are many examples of Rust code where it doesn't seem like the right tool -- but then again, I feel that way about much code written in C++ as well.
- arcticbull 7y agoYou don't spend developer time "thinking" about lifetimes as you write Rust, it becomes totally automatic, no more than you spend time "thinking" about functions in C#. The benefits you get far outweigh the negligible overhead, providing things like data race prevention across threads in addition to memory safety with incredibly low overhead. Modern GCs are faster but they're by no means free, and totally unnecessary if you just give the compiler the information it needs to do its job statically instead of continuing to strap more rockets to the GC rocket-powered horse. It's the fastest horse but it's still a horse, not a car.
- pjmlp 7y agoTry to write a sizeable Gtk-rs application to see how automatically it gets if you don't create your own clone macro to deal with all the Rc<RefCell<>> instances, like the Gtk-rs samples show.
- arcticbull 7y agoI’m not sure a single example of a C wrapper not idiomatically designed is a good example of the potential of a language. It’s like pointing to the source for any given STL implementation as quintessentially C++ coding style. RefCells tend to be considered an anti-pattern AFAIK since they leave invariant checking to run-time. It's meant as a hack/patch if you can't actually design it idiomatically for some reason, such as in this case, FFI to a C programming model.
- Crinus 7y agoWhile i appreciate the type safety that Rust may provide (even if it is overblown and only just a little, it can still be useful - e.g. while i prefer C, i do like C++'s "enum class"), my two main issues are that it is only a single implementation (and that implementation looks is too Unix-y with the Windows versions looking bolted at the side) and -especially- too slow. I get annoyed when my C builds take more than a few seconds and a major reason i avoid C++ for my own stuff (C++'s complexity is another reason) and i hear that Rust has worse compile times than C++. This is enough for me to stay away from it. But if Rust manages to get an implementation that feels at home at Windows with a full IDE and debugger and also gets around C-like compilation speeds, then i'd like to check it out.
- munmaek 7y agoFor what it's worth, Rust will soon improve its linking stage by switching to ldd, as part of upgrading to LLVM 4.0. From what I've read ldd can dramatically reduce the time needed.
- boris 7y agoYou probably mean 9.0.0, 4 is several years old. Or is Rust really still using something pre-4?
- steveklabnik 7y agoNo, we run very close to the latest release; we also have our own patches that we try to upstream. We do support back a little bit, to help distros.
- munmaek 7y agoMy bad, I guess I was confused earlier about something else.
- kbenson 7y ago> and also gets around C-like compilation speeds Isn't that possibly asking for a bit much? The Rust compiler is doing significantly more than a C compiler, so why would be expect it to have C-like speeds? Should we not also expect C to have compile speed improvements in that period, which might leave them relatively unchanged with respect to each other? It feels sort of like you're comparing a Mercedes sedan and Land Rover. Both very capably vehicles, but targeted to excel in slightly different circumstances, and when people suggest a Land Rover for rougher terrain, you're noting that when they can provide the same acceleration and gas mileage as the sedan then you'll be interested, which is both unlikely to happen and missing the point, since an off-road vehicle can do things a sedan just can't. Preferring one over the other is fine, expecting one to be superior to the other in every way is a tall order.
- grok2 7y agoAnybody else found the last variation annoying from a C perspective? I find that people coming from a web background don't mind writing complex statements in function parameters (seems like due to writing lambdas/closures and such encourages this kind of programming; maybe it makes sense in a lazy evaluation environment), but people with a C background use the last-but-one variation where you use an intermediate variable to capture a prior result to use as a function parameter. I myself prefer the last-but-one variation and it's a pet-peeve of mine that people write large functions/expressions/statements as function parameters when not needed all in the name of conciseness -- I think it affects readability.
- jcora 7y agoI use almost no lambdas in my functional code. I don't understand why they're thought to be paragons of FP in non-pure language communities. Maybe because there are no operator sections, currying, and the syntax is more verbose so it's not as easy to define helpers.
- pm215 7y agoIn particular, you can give the intermediate result a useful name (using something more descriptive than 'n' would have helped in the example)...
- k__ 7y agoYou mean, you have to give the intermediate results a useful name. In my experience, this gets ugly rather quick. But yeah, I hope the pipeline operator comes soon, chaining is nice, but nesting can get quite messy.
- steveklabnik 7y agoI probably would not write the code that way either, but it's really hard to say how I would, given that it's not a realistic example. This is one of the hardest parts about writing examples: you want something that's real, but also not long. Very difficult.
- phkahler 7y ago
- agumonkey 7y agothe `{y:2, x:1..=4}` syntax is confusing, is it really range checking ?
- steveklabnik 7y agoYes, it says "match if y is two, and x if it's between one and four, inclusive".
- agumonkey 7y agoWeird couldn't find it in the Book.
- steveklabnik 7y agoWe don't cover this exact combination of features directly in the book; this falls out of composing the "pattern match" feature with the "range" feature. It's also possible that you're reading a version of the book before the ..= syntax was introduced; it hasn't been there since 1.0.
- lacker 7y agoRust is pretty neat and I would like to use it more. It seems like it could be the ideal tool for performance-optimized software, like C++ was 15 years ago. Unfortunately, there isn't all that much performance-optimized software that I am writing nowadays.
- jcmontx 7y agoThe person writing this seems to be a very clever and capable individual. That being said, I would imagine a company the size of MSFT would have a senior engineer coding "a security critical network processing agent". That sounds like a lot of responsibility for someone inexperienced.
- deleted 7y ago[deleted]
- NoGravitas 7y agoPeople promoting Rust tend to assume that it's the concepts in Rust that don't exist or aren't explicit in other programming languages that are the hard part. In my opinion, that's not true. It's the syntax used to make those concepts explicit. To use the example from the article: lifetimes are not a hard concept to grasp. Knowing when the Rust compiler will require you to make a lifetime explicitly part of your type, vs. when you can elide it? Hard.
- steveklabnik 7y ago> To use the example from the article: lifetimes are not a hard concept to grasp. Knowing when the Rust compiler will require you to make a lifetime explicitly part of your type, vs. when you can elide it? Hard. There are only three (or is it four?) rules about when you can elide. Personally? I never write lifetimes, and then the compiler yells at me, and then I fix it by adding them. It's not something that you need to actively think about. You see error[E0106]: missing lifetime specifier --> src/lib.rs:2:8 | 2 | x: &i32, | ^ expected lifetime parameter and you add it in.
- Corrado 7y agoLifetimes trip me up in Javascript all the time. I think that I have all my callbacks and/or promises lined up and dealt and my app runs fine. Until it doesn't and I discover that there is some corner case in my 5 nested deep callback hell where I didn't catch some DB timeout. I'm looking forward to that never happening again in Rust.
- pornel 7y agoUsing types as an analogy: Python and JavaScript programmers know the concept of types, but don't have to be rigorous about it. They can even make a mess of it, and use runtime reflection as a crutch. OTOH with a statically typed language you have no choice but be very precise and explicitly think about types. It's the same with Rust ownership and lifetimes. C programmers know the concept of ownership, but don't have to be rigorous about it. They can use `char *` for both owned and borrowed stings, and make a mess of them (using `need_to_free_that_pointer: bool` as a crutch). When Rust has owned String and borrowed str, it's a surprise. Sure, there's syntax to learn, and it has a few obscure bits if you're into generic programming. But the fighting with the borrow checker Rust is infamous for comes from using a C mindset of "will it crash or leak?" rather than "is this owning or borrowing?".
- diaz 7y agoInteresting. Now if only the images with code actually had the snippets in code form I would be able to share the blog post to other people.