Hacker News new | past | comments | ask | show | jobs | submit login

I think the ‘is or is not a true ML’ argument is a bit unwinnable so I won’t comment on it. Regarding ‘functional’, Rust makes it harder to write in a traditional functional style because (a) it doesn’t offer tail-call elimination and (b) the resource-ownership tracking makes most normal functions feel side-effecty. I think it’s pretty hard to have a natural-feeling functional style without cheap allocation and some kind of deferred automatic deallocation (this is carefully phrased to allow for a garbage collector or a kind of arena allocation)

I don’t think this is that bad for rust though. For (a), it turns out that tail calls can make debugging harder, and they can be incompatible with certain type system changes you might want in an ML, and lots of OCaml (perhaps not a true ML?) in practice uses little explicit recursion and instead first-class functions with names like map and iter rather than recursion. So I don’t really think it’s very important. Rust also has these first-class iterator functions although a bit less of map for containers that can have many things (e.g. vectors). Rust iterations allow for writing code that is more functional when memory/performance are stronger constraints because the pipeline gets composed together instead of producing lots of intermediate objects. For (b) I guess the big difference is that the usual tool in functional programming for manipulating data is creating new copies of immutable data whereas in rust it is controlling ownership and then just updating it (a middle ground may be koka where you write code in the former style but the compiled code inspects recounts to potentially just mutate instead)




For sure, I agree with your points, which is why I write Rust these days instead of OCaml. Sometimes you really just want to get stuff done, while also being faster in execution speed of both the machine and the human.


> it doesn’t offer tail-call elimination

Why not? I’ve heard people say this about C too and I never understood it: LLVM and GCC both have optimization passes that perform tail-call elimination.


Typically when people say that they mean that the language doesn't have guaranteed tail-call optimization. You can certainly write Rust that has the TCO pass applied, but it can be brittle because it's just an optimisation pass that might not happen.


I don’t know the actual reason. It may have been a desire to keep flexibility in the language design by not imposing TCE rules. I think one reason is that you can’t have a tail call if you need to free things afterwards, so changing the signature from taking an object to borrowing it could make calls to the function no-longer eliminatable. Rules for which calls are tail-calls can already be confusing to people in simpler languages.

I think they also make debugging harder, aren’t used much in higher-level code, and aren’t necessary if you have good looping constructs.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: