Hacker News new | ask | show | jobs
by lvass 1225 days ago
Can someone explain why/whether a language like Rust requires mutability? Wouldn't it be better if we could just have the compiler guarantee that functions marked as such are doing TCO, so algorithms would look better and had the full benefit of persistent data structures?
7 comments

The price for immutability is pretty high. Haskell garbage collection has a lot of work to do.

When you say 'algorithms would look better' this is pretty subjective. Graph based algorithms or inplace algorithms doesn't look too good in haskell.

In-place maybe not, but what language would be more suitable for graph based algorithms? Of course it depends on how you represent the graph, but writing something like breadth-first search is quite nice and easy to implement in Haskell, in my experience.
This is maybe just me but I find any kind of self referenced data structure a bit awkward to define in haskell. The thing mentioned in http://wiki.haskell.org/Tying_the_Knot .
I generally express graphs as a `Map k (Set k)` or similar, with extra data as desired. Using keys and lookups means you don't need self-references. I guess in a way this approach sacrifices some purity, but I find it works very well.
Rust is designed for maximal performance, so it's designed to be close to machine language, where mutability is an unavoidable reality. That's pretty much the whole story.
> Can someone explain why Rust has mutability?

Because it’s target domain requires reliable efficiency.

> Wouldn't it be better if we could just have the compiler guarantee that functions marked as such

As such what?

> are doing TCO

TCO is worthless, and Rust does not have TCE, nor does it care about TCE.

> so algorithms would look better and had the full benefit of persistent data structures?

Rust does not significantly care for persistent data structures, there are crates which provide them, but not the standard library.

Rust is not a functional language.

"Worthless" is a bit strong. The Rust devs want to add TCO/TCE, but there are still problems left to solve. The "become" keyword is already reserved in anticipation of guaranteed tail calls being added.

https://github.com/rust-lang/rfcs/issues/2691

> "Worthless" is a bit strong.

No, TCO is worthless, it’s an unreliable optimisation.

Compiler optimizations are best-effort. -O3 gets you 90% of the optimization for 10% of the work of writing hand-rolled assembly. Individual optimizations are not guaranteed, and sometimes even regress in newer compiler versions, but everyone uses them because overall programs run much faster with optimizations than without. I don't see how TCO is any different. Would you say all optimizations are worthless because they're not guaranteed?
> Would you say all optimizations are worthless because they're not guaranteed?

Context is relevant, the context here is language semantics, not things going faster.

TCO is fine to make things go faster, like inlining, unrolling, LICM, ....

TCO is hot garbage when you rely on it for program correctness.

Weird how none of that context was present in your first two iterations of the claim.
If given explicit support in a language then no it's not. Especially with the keyword approach rust is taking, the compiler will guarantee the semantics.

Do you believe the exec system call is similarly unreliable at replacing your process image? Amazing that unix systems work at all

> If given explicit support in a language then no it's not. Especially with the keyword approach rust is taking, the compiler will guarantee the semantics.

Then it's TCE not TCO.

> Do you believe the exec system call is similarly unreliable at replacing your process image?

Exec is entirely unlike TCO. If exec was a syscall which sometimes did and sometimes did not replace your process image, then it'd be like TCO, and it'd be similarly unreliable.

I think it would have helped if you'd defined your terms earlier. Wikipedia, for example, doesn't distinguish between the terminology TCO and TCE: https://en.wikipedia.org/wiki/Tail_call
>"Can someone explain why Rust has mutability?"

Why not? Why this "there can only be one" mentality?

Others have already said why Rust has mutability, but in the spirit of the question I would like to share https://koka-lang.github.io/koka/doc/index.html which I think looks a bit like Rust if it had very limited mutability. (It has a "sufficiently advanced compiler" - an implementation of the Perceus static reference counting - that still makes the resulting code extremely fast)
You mean mutability annotations or allowing mutability at all?

Because you can't simply disallow mutability in an imperative language.

But about annotations, you annotate your code to let the compiler know what you meant to do. If just looking at what you do was enough, C would be a safe language. You improve it by giving more information to the compiler, so it can check if you are doing what you meant to.

(But I don't know what relation you saw with TCO. It's not a related concept.)

Maybe because otherwise you need a 'sufficiently smart compiler' which will be able to extract the right amount of performance from the underlying hardware which is mutable. Also I don't know if you can implement persistent data structures without a gc and with the rust typesystem.

Maybe because it's designed to replace existing, familiar imperative and mutable languages.

> Also I don't know if you can implement persistent data structures without a gc and with the rust typesystem.

Well you can use Rc/Arc (that’s what Bodil’s imrs does for instance), but essentially yes, by design and purpose a persistent data structure has confused ownership, and thus requires a separate layer handling memory reclamation.