[erlang-questions] Reassigning variables

John Haugeland <>
Sat May 9 17:27:43 CEST 2009


So I'm digging through my mailing list backlog, and I see this.

> I like pattern matching in the majority of cases, but I find I write
> enough code where I need to incrementally update a data structure, and
> maintaining that code is a pain when I have code like:
>
>  X = foo(),
>  X1 = bar(X),
>  X2 = xyzzy(X1),
>  blah(X2).
>
> and later want to change it to:
>
>  X = foo(),
>  X1 = whee(X),
>  X2 = bar(X1),
>  X3 = xyzzy(X2),
>  blah(X3).

This goes through IRC a lot.  This is a result of poor variable naming
practice, and there is no need to introduce rebinding to "fix" it;
just stop using single letters and counters as variable names.

If for example that was written

    FooStateX    = foo(),
    PostBarX     = bar(FooStateX),
    OnceXyzziedX = xyzzy(PostBarX),
    blah(OnceXyzziedX).

then there would be no need for a rename.  Inject the new line, edit
the successor line, and all's done.

It is tempting to suggest that even so, there is a "savings" in the
rebinding approach wherein the successor need not be updated; that
savings prevents the compiler from enforcing you to observe the point
at which the data being fed upstream has legitimately changed (which
it must have, or you wouldn't be trying to rebind something.)

A different way to look at it is the well understood best practice of
meaningful names: code that's expected to be throwaway code often ends
up being a long term underpinning, and having meaningful labels
attached to names makes the intent of the original developer clear,
which is critically important during maintenance, extension and
late-stage debugging.  Suddenly if you inject the new step in the
wrong place and move on, a third person could come by and see the
error quite easily, by remembering the intentional relationship of
state names to functional transformations.

The reason this can happen is that you've used a wholly meaningless
name: "X".  X could be anything, so you don't get concerned that
you're changing its meaning.  If these intermediate data states had
appropriate names, suddenly you wouldn't even want rebinding, because
the result of each of those functions doesn't /belong/ inside those
other names.

If you really want dense code, you'll write blah(xyzzy(bar(foo()))).
You appear to be trying to write code that's maintainable and
understandable.  There's more to that than peeling apart function
towers.  Don't do the job halfway.  Use meaningful names everywhere -
including in internal intermediate state variables - and this
"problem" disappears along with several other problems not being
discussed.

There is a third, rather more subtle downside to rebinding - many
people will misunderstand it to be mutability, and attempt to leverage
the significantly different performance and correctness semantics of
mutability therein.

Rebinding isn't particularly meaningful.  Just write better code.



More information about the erlang-questions mailing list