Hacker News new | ask | show | jobs
by rbehrends 4030 days ago
> Go ahead and tell us what benefits and detriments you're already aware of, having thought about the question, and I'll tell you if you've missed anything.

Just a second, let me put on my Eiffel/Ada hat for this question.

The contract between a caller and callee is a potentially complex thing; it specifies not only which arguments can be mutated (if at all), but also how their abstract state before and after relate to each other or what other visible side effects may be produced. I refer you to the Eiffel and Ada language specifications for possible ways to specify such contracts, invariants, and pre- and postconditions. Common convention is that functions that return a value do not have visible side-effects at all (the Ada '83 rationale specifically found limitations that disallowed all side effects at the language level too limiting). See: Command-query separation. Adhering to CQS, queries do not mutate arguments, and commands are expected to; hence, you need to know the specific contracts for commands and how they affect their arguments, but can rely on query arguments not changing.

More generally, mutability of arguments is just one aspect of a contract; importantly, in order to be able to optimize or change the internal representation of an object, we may desire the option of having mutability of the concrete state even where the abstract state remains immutable (e.g. splay trees or self-organizing lists, arguments that have internal caches, etc.). Languages that force a knowledge of immutability of the concrete state at the call site can thus violate principles of modularity in that they limit how the implementation may change.

Declarations of immutability of only the location of the variable at the call site (as with out/ref parameters in C#) are of even more limited value; while they guard against some clerical errors, it is not clear that this protection justifies the additional syntactic footprint.

Back to Nim: The simple solution to ensure that a variable is not being modified by the callee, if you desire that, is to use a "let" rather than a "var" declaration. In fact, using "let" for values that you do not intend to change further and only use "var" variables where they are expected to be mutated throughout a procedure is already idiomatic Nim [1] and should guard against the majority of related clerical errors of this kind.

[1] https://github.com/Araq/Nim/wiki/Style-Guide-for-Nim-Code