4 ms·
I just released a big-ish open-source project in Rust that I've been working on since June 2016. https://github.com/postmates/cernan https://github.com/postmat
by troutwine 10y ago
I just released a big-ish open-source project in Rust that I've been working on since June 2016.
https://github.com/postmates/cernan https://github.com/postmates/cernan
Cernan has to be sparing in its memory consumption, be a good citizen with regard to its CPU impact–at Postmates we deploy it as a ride-along with application servers--and be correct even though there's changes being made at a punishing pace.
When I started cernan I'd been following Rust for a while but had _not_ written anything of note in it. My estimation, though, was that Rust would be a better fit for cernan than C++:
* It'd be easier for colleagues knowing neither Rust nor C++ to review Rust code.
* If I got hit by a bus, the Rust compiler would make stronger behaviour constraints for me.
You can see in the first month https://github.com/postmates/cernan/commits/master?after=Y3Vyc29yOkQtl3zrI07%2BiO53gHPQv%2FNM7ljgKzEzOQ%3D%3D https://github.com/postmates/cernan/commits/master?after=Y3V... that I flailed around a bit. I was internalizing the borrow checker's view of Rust's memory model, getting used to the tooling and the ecosystem of crates available. One thing I particularly had issues with from the get go and have _kind of_ resolved are many wee allocations inside cernan. In some sense they're inevitable but my early ignorance exacerbated the problem: I'd clone to convince the borrow checker to let me move on, would construct new containers rather than pass new ones in to be refilled and the like. Also, strings. Lots and lots of strings everywhere.
After the first month, toward the back half of the second I felt like I was flying finally. Still plenty I needed to internalize or learn about but I had a cohesive mental model in which to incorporate new information.
- anamoulous 10y ago> In some sense they're inevitable but my early ignorance exacerbated the problem: I'd clone to convince the borrow checker to let me move on, would construct new containers rather than pass new ones in to be refilled and the like. Also, strings. Lots and lots of strings everywhere. I've been teaching myself Rust in the evenings for a couple of weeks now and have found the process maddeningly confusing and slow. Even with the Book, which is fine, I ended up getting into rage induced clone/to_owned/etc keyboard mashing dances with the borrow checker. If it weren't so easy to do this kind of dev with emacs, I might have given up earlier. On the other hand I occasionally get these moments where my code just "clicks" and it feels good and _seems_ elegant. But, pedagogically speaking, at this point I'm just trying to learn through immersion, not through theory and understanding. Honestly I'd probably be way done with this little project if I had started in Go, but I think I'm going to stick with Rust for a while.
- troutwine 10y ago> I'm just trying to learn through immersion, not through theory and understanding. Oh hey, that's a pretty good way of putting it. For me, internalizing the borrow checker is where I had the hardest time. Much of what the borrow checker formalizes is best-practices in C++ but it's a surprisingly different experience to have a robot come and check what you ought to have been doing anyhow. Maybe I found it even harder to adapt because while my C++ is passable I'm no guru. But! Immersion for sure works and I'm _really_ glad I stuck it out. Now that I'm on the other side I can see that the borrow checker is a novel invention and novel inventions are _very_ difficult to explain at first.
- chias 10y ago> I'd clone to convince the borrow checker to let me move on, would construct new containers rather than pass new ones in to be refilled and the like. Also, strings. Lots and lots of strings everywhere. This is where I'm at right now. When the borrow checker yells at me, I find I can generally fix it with a .clone() or a .to_string(). I'm new enough with the borrow checker that I'm not quite sure when such cloning is necessary and when I'm unnecessarily allocating more memory -- or more importantly, what I should be doing instead when it's not necessary -- but I hope that as I write more code, I'll get better at it :) A bad habit that I've fallen into is to needlessly allocate in order to avoid having to think about lifetimes. As in, better change that struct to make that str a String -- and then not have to worry about lifetimes at all. That's just laziness, though...
- akiselev 10y agoThis is the going advice many Rustaceans give to beginners. Cloning something in Rust is nothing like cloning in dynamic languages where you need to notify a garbage collector and allocate heap memory. Rust is fast and copying data is fast, especially if you're cloning a stack only value to satisfy the borrow checker. Make it work, then make it correct, then make it fast. Chances are you'll never need that last step for most code you write. Edit: another thing you'll learn with practice is when to make the right trade offs. Rust has lots of types in the standard library that allow you to pick and choose which guarantees you want the compiler to uphold and whether to do it at compile time or run time. Check out "Choosing your Guarantees" in the new version of the rust book [1] [1] https://doc.rust-lang.org/beta/book/choosing-your-guarantees.html https://doc.rust-lang.org/beta/book/choosing-your-guarantees...
- dbaupp 10y agoCloning anything nontrivial (String, Vec, structs containing them, which is when cloning is usually used to ease things) does need to allocate. The comparison to managed languages doesn't make sense: "notifying the GC" sounds exactly like "notifying the memory allocator" in Rust/C/C++.
- 10y ago
- the8472 10y ago> getting used to the tooling I'm still missing an IDE that spits out inferred types including generics when hovering in the middle of chained method calls. Especially in iterators it's often hard to know what it's currently passsing as arguments into some closure. That situation is much much better in java-land.
- dumindunuwan 10y agohttps://intellij-rust.github.io/ https://intellij-rust.github.io/
- the8472 10y agoNo, it does not seem to use information from the compiler to get the actual types. It seem like it sometimes does something based on imports or something like that. But it fails even on trivial code: https://i.imgur.com/mPUbrFP.png https://i.imgur.com/mPUbrFP.png
- steveklabnik 10y agoThis is coming! A demo from a few months ago: https://youtu.be/pTQxHIzGqFI?list=PLE7tQUdRKcybLShxegjn0xyTTDJeYwEkI&t=2536 https://youtu.be/pTQxHIzGqFI?list=PLE7tQUdRKcybLShxegjn0xyTT... (A more general description of this work starts around 40:09)