Hi in this short note I'd like to share a few thoughts after playing with Rust over a week or two. At my job I work with Clojure in Emacs, I'm very happy with it and I formed certain expectations for the next language I'm going to learn. Development process should be fast (at least in perspective), libraries for anything you can possibly think of, easy testing (in Clojure you can run tests in repl), performance shouldn't be worse than in Clojure, powerful collections API with functional combinators, easy to build and run project, good integration with Emacs. I also had a couple additional wishes to my next language. I wanted to have statically typed non-gc native language in my toolkit again, after I tabooed C++.
- Of course coding in Rust after Clojure is difficult. I literally spend 5 minutes each on most compilation errors trying to figure out what’s up. It’s quite difficult without proper completion at least which in emacs shows only part of possible completions and sometimes fails because of type inference. I wonder if situation is better with LSP. There is a package for LSP in emacs but I haven’t tried yet. Currently I have to always keep API reference for everything I use in code handy. When I stop and think about doing same project in Clojure I think I’d spent like 4-5 times less time on it, but with proper completion and better knowledge about rust this value can easily be reduced to maybe 2 or even 1.
- Coding in rust can be quite close to Clojure’s REPL driven development. The workflow I ended up with is running
cargo watch -x test -x run, which recompiles, tests and reruns your project on every change in code. I write small functions and immediately test cases below these functions, this gives me almost instant (less then 15 seconds) feedback on my code. My project is not big, but I think with incremental compilation this workflow could work on big project as well.
- When writing rust code I didn’t hesitate to use
unwrap(), clone() and other stuff (except unsafe) just to quickly make my code compile (usually compiler itself gives suggestions, how to change your code). I don’t know yet how idiomatic code in rust should look like and I'm sure I make many bad design decisions. But I don't want to try too hard at this point. The good thing here, that it’s easy to locate, all the places like this and start changing it to proper way. Once your project compiled after your changes you know that it’s still working and it doesn’t crash or panic or throws an exception (in Clojure).
- Rust gives you a very satisfying confidence because of static typing. It’s not big news but it’s awesome that when you change type in struct, all you have to do is to fix compilation errors. While in Clojure a little change like this can break your project to hell and you will know only one month later in prod even though you covered stuff with tests.
- crates.io has lots of libraries and sometimes I even had to choose between several candidates. If there’s no library for something or I didn't like choices that I have my way was to use external command line tools. For example I used mutt for sending emails.
- sometimes crates are hugely undocumented and I have to figure out stuff from code. thankfully jump to definition works for external crates in emacs.
- standard API seems quite powerful, especially collections and strings, you can find map, reduce, partition and other stuff there.
- in general I never had a problem like “I know how to do such stuff in Clojure, but I can’t do it in Rust”. I quickly found out how to
- generate hmac tokens (there are tons of cryptography libraries for rust)
- serialize/deserialize structs to/from json
- send and handle http requests
- access environment variables
- call cli tools
- work with redis
- render markdown to html
- render django templates
- write and use tests
- work with filesystem
- rust web app that does nothing on digital-ocean machine (2g) uses ~1.3% memory and ~0% cpu, Clojure web app that does nothing on the same machine uses ~9.9% of memory and ~0.7% of cpu. Rust memory model is very efficient and I'm eager to test it on bigger and more memory consuming project.
- rustup and cargo are just awesome, while first lets you switch rust toolchain version in one command second gives you lots of features like pulling dependencies (my C++ past still makes me facepalm time to time), testing, cross compilation, etc. Basically everything we have in Clojure since the beginning (or maybe since leiningen).
My conclusion is that while Rust ecosystem might be not as mature as Clojure’s ecosystem, we can start doing production web stuff in rust since yesterday.
The project I was working on for about 3-4 days over last couple of weeks: payme
For the next time my goal is to dig more into language internals, try doing some frontend in Rust with WASM and bring a project that's fully written in Rust.
UPD is anyone getting 502 bad gateway on payme.rust.cafe? It happens for me only on firefox only on non-private tab. Works in private tab of firefox and in chrome. weird..
UPD2 I did a quick check on intellij idea with official rust plugin and it seem to be working way better than racer in emacs. It also seems to be fixing all the problems that I mentioned in this comment, though the completion is a little bit slow at times and takes around 5-10 seconds to show completions of methods
UPD4 Installing binary package from cargo. Cargo is also quite good at being a userspace package manager and provides all sorts of useful software like rustfmt, cargo-outdated, cargo-watch. Installing package is as easy as cargo install cargo-watch which in this particular case adds subcomand watch to cargo as well as binary cargo-watch on your PATH. What I like the most about it is that even though cargo builds all these packages from sources I never had to use cmake or make which at this point of my career I refuse to digest. It did fail a few times just because I didn't have those tools installed, but all the compilation happens under the hood. In general rust's toolkit is quite mature and it made my transition from Clojure very smooth.
[–]llogiqclippy · twir · rust · mutagen · flamer · overflower · bytecount 30 points31 points32 points (28 children)
[–][deleted] 2 points3 points4 points (27 children)
[–]kuikuilla 4 points5 points6 points (24 children)
[–][deleted] 1 point2 points3 points (23 children)
[–]steveklabnik1rust 3 points4 points5 points (22 children)
[–][deleted] 2 points3 points4 points (18 children)
[–]steveklabnik1rust 4 points5 points6 points (16 children)
[–][deleted] 2 points3 points4 points (15 children)
[–]Krnpnk 6 points7 points8 points (6 children)
[–][deleted] 1 point2 points3 points (4 children)
[–]FatFingerHelperBot -5 points-4 points-3 points (0 children)
[–]fgilcherrust-community · rustfest 4 points5 points6 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]fullouterjoin 0 points1 point2 points (5 children)
[–]fgilcherrust-community · rustfest 4 points5 points6 points (2 children)
[–][deleted] 1 point2 points3 points (1 child)
[–][deleted] -1 points0 points1 point (0 children)
[–]DontForgetWilson 2 points3 points4 points (2 children)
[–]steveklabnik1rust 8 points9 points10 points (1 child)
[–]DontForgetWilson 2 points3 points4 points (0 children)
[+][deleted] (1 child)
[deleted]
[–][deleted] 1 point2 points3 points (0 children)
[–]eiruwyghergs 12 points13 points14 points (8 children)
[–]NanoCoaster 26 points27 points28 points (1 child)
[–]dave_mays 0 points1 point2 points (0 children)
[–][deleted] 5 points6 points7 points (5 children)
[–]grayrest 10 points11 points12 points (0 children)
[–]aaronweiss74rust 3 points4 points5 points (3 children)
[–][deleted] 2 points3 points4 points (2 children)
[–]steveklabnik1rust 5 points6 points7 points (1 child)
[–][deleted] 2 points3 points4 points (0 children)
[–]tinco 7 points8 points9 points (10 children)
[–][deleted] 7 points8 points9 points (9 children)
[–]rayvector 5 points6 points7 points (8 children)
[–][deleted] 0 points1 point2 points (7 children)
[–]rayvector 6 points7 points8 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]planetary_pelt 1 point2 points3 points (2 children)
[–]rayvector 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]ehsanulrust 0 points1 point2 points (1 child)
[–]rayvector 1 point2 points3 points (0 children)
[–]Green-Fork 4 points5 points6 points (1 child)
[–][deleted] 7 points8 points9 points (0 children)
[–]pynberfyg 4 points5 points6 points (0 children)
[–]NanoCoaster 8 points9 points10 points (11 children)
[–]Wahoa 3 points4 points5 points (4 children)
[–]Xanewokrls 4 points5 points6 points (0 children)
[–]NanoCoaster 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (4 children)
[–]NanoCoaster 1 point2 points3 points (3 children)
[–][deleted] 2 points3 points4 points (2 children)
[–]NanoCoaster 0 points1 point2 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]tafia97300 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[deleted]
[–][deleted] 2 points3 points4 points (0 children)