[erlang-questions] Reassigning variables

Ulf Wiger <>
Thu Mar 19 01:21:39 CET 2009


Matthew Dempsky wrote:
> On Wed, Mar 18, 2009 at 11:37 AM, Ulf Wiger
> <> wrote:
>> Whether it's more readable is perhaps a matter of
>> taste. It ought to be easier to maintain though.
> 
> That only eliminates three of the St updates.

...because I stopped there. It would have been
possible to reduce more with some minor rewrites,
but I thought that I had made the point already.

It reduces the amount of numbered variables. It
doesn't eliminate them entirely, and I didn't
claim that it was more readable in this
particular case. In fact, I'd say it's slightly
less readable, but I've been bitten by numbered
variables enough times that I'm now willing to
sacrifice some time and convenience in order to
avoid them. They can be the cause of some very
subtle bugs.

In this particular case, though, the code is
pretty symmetric to begin with, so even doing
some slight re-formatting...

lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], Mc, St0) ->
    {Gs,Qs1} =  splitwith(fun is_guard_test/1, Qs0),
    {Name ,St1} = new_fun_name("lc", St0),
    {Head ,St2} = new_var(St1),
    {Tname,St3} = new_var_name(St2),
    LA = lineno_anno(Line, St2),
    LAnno = #a{anno=LA},
    Tail = #c_var{anno=LA,name=Tname},
    {Arg   ,St4} = new_var(St3),
    {Nc,[] ,St5} = expr({call,Lg,...}, St4),
    {Guardc,St6} = lc_guard_tests(Gs, St5),
    {Lc,Lps,St7} = lc_tq(Line, E, Qs1, Nc, St6),
    {Pc    ,St8} = list_gen_pattern(P, Line, St7),
    {Gc,Gps,St9} = safe(G, St8),
    ...

...will improve readability and make it easier
to make sure that at least the numbered variables
in the LHS aren't messed up. But the uses of
numbered state variables in the actual calls are
harder to spot, and often, this is where the bugs
are - we use an older instance of the state in
a call and overlook some recent change.

 > The snippet of code I posted has nine St updates.
 > Not all of them output data in the same format
 > (i.e., a tuple with the result and a new state)

Actually, they pretty much did. Some functions
returned {A, B, St} instead of {A, St}, but this
is obviously easy to fix, either by modifying the
called function so that it returns {{A,B},St}.

I don't think it's uncommon to have to re-think
return values etc when you make a change like this.

> and some of them take previous outputs as their own
 > arguments,

Sure, so you'd need to do it in multiple stages.

> but even ignoring that, if you were to put all
 > nine updates in your format, that requires
 > maintaining a list of 9 variable outputs and
 > making sure that they're in the same order as
 > the 9 state-mutating function calls.

Right, it's not a panacea. Sometimes it makes for
more readable code, but if you go overboard with it,
it won't. ;-)

> I don't think that's easier to maintain than 
 > being able to selectively rebind a single
 > St variable.

In my opinion, numbered variables are sometimes
an acceptable cop-out because alternatives are
less practical (or at least defy your imagination.)

But I think that folding over funs is an under-
appreciated technique. Possibly because there
isn't (directly) a library function for it, but
also surely because the fun(...) -> ... end
syntax is a bit bulky.

BR,
Ulf W
-- 
Ulf Wiger
CTO, Erlang Training & Consulting Ltd
http://www.erlang-consulting.com



More information about the erlang-questions mailing list