[erlang-questions] Versioned variable names

Mikael Pettersson mikpe@REDACTED
Tue Jun 9 18:22:57 CEST 2009


Attila Rajmund Nohl writes:
 > Hello!
 > 
 > I think there wasn't any grumbling this month about the immutable
 > local variables in Erlang, so here's real world code I've found just
 > today:
 > 
 >     % Take away underscore and replace with hyphen
 >     MO1 = re:replace(MO, "_", "-", [{return, list}, global]),
 >     MO2 = toupper(MO1),
 >     % Replace zeros
 >     MO3 = re:replace(MO2, "RX0", "RXO", [{return, list}, global]),
 >     % Insert hyphen if missing
 >     MO5 = case re:run(MO3, "-", [{capture, none}]) of
 > 	      nomatch ->
 > 		  insert_hyphen(MO3);
 > 	      match ->
 > 		  MO3
 > 	  end,
 > 
 > I think it's fairly clumsy to use MOx (MO for managed object) in the
 > code. MO4 was removed during the regexp->re refactoring step. How to
 > eliminate the versioned variable names? The
 > MOAfterUnderscoresWereReplaced, UpperCaseMO, MOAfterRX0WasReplaced,
 > etc. variablenames are really ugly. It used to use regexp, so at that
 > point it wasn't possible to easily nest the whole into one call, but
 > that would be still ugly. So any other ideas?

This has nothing to do with mutable variables (values or
bindings), and everything to do with Erlang's unorthodox
(for a functional language) scoping rules and semantics
for "Var = Expr".

Languages using LET for local bindings tend to allow you
to re-bind already-bound variables in nested scopes. For
instance, in Standard ML I would often write:

fun f (..) =
  let state = init()
      state = stage1(state)
      state = finish(state)
  in
    ... state ...
  end

and similarly in Scheme using LET*.

In Erlang you can't do this, so you're stuck with:
- numbered variables (ugly but often reasonably practical)
- function composition like f(x) -> a(b(c(x))), but that
  quickly gets unreadable
- using a separate function for each stage and tailcall
  between the stages:
	  f() -> g(init()).
	  g(X) -> h(update(X)).
	  h(X) ->
	    NewX = if ... -> update2(X); true -> X end,
	    i(NewX).
	  i(X) ->
  this doesn't entirely eliminate the variable naming problem,
  but it does limit it to say two versions per function body,
  which is manageable (I use this approach quite a lot in the
  HiPE compiler backends when translating generic intermediate
  code to architecture specific code)
- foldl (as another poster suggested), which is essentially
  equivalent to function composition or using tailcalls between
  per-stage functions, except it's expressed in different syntax


More information about the erlang-questions mailing list