I looked seriously at rust about 2 years ago. I seem to have tried the language at the wrong time .. they were transitioning between versions and this made learning it hard. I grew up with C so am very comfy with pointers. Even reference counting feels natural to me. That said, the borrowing/ownership semantics of rust (at the time I looked at it) felt needlessly over complicated. Has this got better? Is there a K&R…
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).