
Should function arguments be reassignable or mutable? - ingve
https://mortoray.com/2017/12/31/should-function-arguments-be-reassignable-or-mutable/
======
mabbo
I feel the author isn't going far enough- make all variables immutable by
default unless explicitly declared otherwise, and even then highly
discouraged.

Where mutable variables are needed, I prefer to hide that logic inside a
method that exists solely to do that dirty business on an abstract level, not
specific to my business logic. That let's me test the 'dirty' mutable method
in an isolated place and removes a whole class of mutability-related bugs from
my business logic code.

Working on Java, this used to be nigh-impossible, but the Java 8 additions
have truly made my life easier.

~~~
cuspycode
Historical anecdote: Algol-68 disassociated variable assignment from
mutability already 50 years ago. Whenever mutability was desired, a reference
to a mutable value holder was used.

Example of immutable assignment: _int n = 2_

Example of reference to mutable value: _ref int n = (heap int := 2)_

However, in order to make Algol-68 code look more similar to Algol-60, they
introduced backwards-compatible shorthands, so for example the declaration
_int n;_ was actually a shorthand for _ref int n = (loc int);_

This shorthand magic probably contributed to why Algol-68 syntax was perceived
to be difficult.

Footnote: loc and heap were the two memory allocation operators available in
Algol-68.

~~~
sli
Rust takes a similar approach with _let some_var_ and _let mut some_var_ ,
respectively.

------
emerged
I'm having a hard time understanding why they should be treated any
differently than normal variables. I suppose the way that I view parameters is
as regular variables who are initialized to values provided by the caller. Is
there any argument against default mutability which still makes sense when
viewing parameters from this perspective?

~~~
mighty_bander
The difference between a local variable and a function argument is that
altering the argument has an effect outside the function, and that the effect
is invisible in that calling the function doesn't tell you that it will change
the argument's value. It is a minor sin in the case of e.g. massaging data to
turn NaNs into 0s or provide default values. It is also fine in the case of
performance-critical code: c string manipulation functions might move a
pointer along the string's length. However it is much easier to program
against a function which has a single predictable result, ideally the
generation of a return value based on input. If you mess with a function's
input, you had better a) document that fact and b) have a reasonable
expectation that your consuming dev is going to read the documentation. C
programmers have this one tiny luxury; authors of an npm package do not.

~~~
emerged
Ok sorry, I didn't make explicit an important bit -- from my perspective these
variables are initialized by the callee but are otherwise local to the
function. From a C perspective imagine them as function local variables which
are contructed by the callee's parameters.

------
runeks
> If we look to a language like Haskell we see that reassigning variables, in
> general, is frowned upon (is it even possible?)

This is perfectly valid Haskell:

    
    
        main = do
          let a = 7
          print a
          let a = 9
          print a
    

but you'll get a warning for it: _tmp.hs:4:7: warning: This binding for ‘a’
shadows the existing binding bound at tmp.hs:2:7_

~~~
weinzierl
The warning says it right away, the first _a_ is shadowed, not reassigned,
here.

The difference is that when _a_ is reassigned the 7 is lost, while it should
be still around when shadowed. I don‘t know of a way to access the 7 in this
example however.

~~~
runeks
If there’s no way to access the 7 after it’s shadowed, why couldn’t an
optimized garbage collector throw it away after it’s shadowed, thus making it
equivalent to reassignment?

------
EtDybNuvCu
Members of the E family permit `var x` instead of `x` for reassignable
arguments. Having immutable names by default with a keyword to make a mutable
name has worked well.

------
tjwii
I think immutability of arguments should be optional by using a const keyword,
like in c:

    
    
      int add(const int a, const int b);

~~~
bmm6o
The downside to this syntactic approach is that the implementation details are
leaked in the signature.

