"I have a mind like a steel... uh... thingy." Patrick Logan's weblog.

Search This Blog

Sunday, July 27, 2008

Calling Names

I'd not heard of this before, but apparently some people don't like Erlang's "single assignment" semantics. What this means is a "variable" actually isn't. A variable becomes "bound" to a value via pattern matching. Once bound to a value, that same variable in that same lexical scope cannot be re-bound to some other value. Within that scope that variable must subsequently match successfully against the value it currently has.

What appears to be an "assignment" in Erlang is really just the simplest kind of pattern match. Below X10 is matched against foo(X) and since X10 is not yet bound, it becomes bound to the value of the function.

f(X) ->
  X10 = foo(X),
  X15 = fab(X10),
  X20 = bar(X15),
  baz(X20).
Some people are concerned this could lead to uncomfortably renumbering variables, say, when the function fab should be added in the function above.

I dunno. This seems contrived, or at least rare, or maybe machine-generated. If you just have to "re-number" a few variables, no big deal. If you have to renumber too many variables then you'd be better served by decomposing an overly long function that also suffers from inexpressive variable names.

The author of the post is apparently writing a ruby-ish language for the Erlang runtime. More power to you.

But there is a lot to be said for a simple, mostly functional language that wants you to keep functions short. When I am writing in an imperative, even object-oriented, language, I want my procedures to be short. And I want one variable to have one value. The code is more "tractable" when short, and variables don't vary.

Then the name becomes essentially a mnemonic for the value.

The overwhelming majority of programmers have only used languages with multiple assignment.
The overwhelming majority of programmers over my 25+ years of programming experience write procedures that are much too long, even when they are otherwise well-written. That's the first bad habit people seem to adopt, or never learned to avoid. I've worked with long, run-on procedures in every language I've encountered.

Lisp? Yes. Smalltalk? Yes. Pascal? Yes. Even these languages with their gifts for brevity cannot overpower the usual programmer's inaesthetics.

Understanding what many, small procedures do is always better than understanding what one or a few long, run-on procedures do. The payoff is there because you learn what you can put aside, and what you should pay attention to. On the other hand, long, run-on, convoluted noise is always with you. You never can put any of it aside - you have to revisit, remember, and ultimately revolt and/or refactor.

In an imperative language a variable should take multiple values only as part of an iterative statement. In the statement "for i = ..." the variable i should only be updated by this statement. Or in "while someCondition ..." the variable someCondition should be assigned an initial value before the while and it should be updated immediately before the while re-evaluates its decision to iterate again.

Write short functions. Use the shortest name that yet conveys the meaning or purpose of its value. Assign them once even if your language is imperative. Generally this will keep your stress level low, as well as the levels of those who pick up your code later.

7 comments:

Pichi said...

Yes, that's all. Write your code well and than Erlang is good enough for you. I like Erlang because it is pushing your code to better quality.

Nat Pryce said...

Suffixing variable names with numbers is a terrible practice in itself.

Maybe the problem is that (Ruby, Java) programmers don't know how to rewrite an iterative algorithm that uses mutable variables as a tail-recursive algorithm with accumulator parameters.

baxter said...

Steve Vinoski addressed this problem in a previous post:

http://steve.vinoski.net/blog/2008/03/10/damien-katz-criticizes-erlang/

Ian Bicking said...

I use reassignment a lot when decomposing awkwardly long expressions into multiple expressions, or performing conversions. A common example would be:

i = int(i)

I can understand why that seems a little wrong, but I also don't really want to create a distinct notion of the-number-before-being-converted-to-an-int and the-actual-number. There aren't two usefully different things there. Another example might be converting an empty string to a null object (or vice versa). That I spend some time at the beginning of functions working out little details of the inputs, error checking, etc, doesn't make me feel like the function is any logically longer or needs to be decomposed.

Anonymous said...

What this means is a "variable" actually isn't."

We programmers have confused the issue. The term "variable" doesn't mean the value contained may change, but rather that the value it will contain may be different. In Joe Armstrong's book he briefly mentions how in mathematics a variable always has the same value; Erlang is the same way.

As a total Erlang noob I'm not able to speak about the relative merits of single- versus multiple-assignment, but in reading through tutorials and books it occurs to me that single-assignment is a feature, with which you can create control structures and other interesting behavior (why else is the otherwise-ubiquitous "if" statement so trivialized in Erlang?)

Alexey Romanov said...

Actually,
1. To create control structures you just need closures;
2. "if" is much less used because of pattern matching.
Both are very nice features which are completely orthogonal to single-assignment (less so for pattern-matching).

Robert Virding said...

One clear benefit I forgot to mention was that with this form of variable renaming is that you clearly “see” the progression of data and who may have modified it. It is also very clear which version of the data you are using. A typical use is when passing state through a function:

foo([A|As], State0) ->
{X,State1} = bar(A, State0),
{Y,State2} = baz(A, State1),
{Rs,State3} = foo(As, State2),
{[{X,Y}|Rs],State3}.

Wrote an extended comment around this on http://tonyarcieri.org/articles/2008/07/26/the-single-assignment-cargo-cult.

Blog Archive

About Me

Portland, Oregon, United States
I'm usually writing from my favorite location on the planet, the pacific northwest of the u.s. I write for myself only and unless otherwise specified my posts here should not be taken as representing an official position of my employer. Contact me at my gee mail account, username patrickdlogan.