Sometimes I miss destructively updating local variables

Richard Carlsson richardc@REDACTED
Fri Jul 7 14:23:48 CEST 2006


James Hague wrote:
> Often I find myself writing a function that's just a case statement
> where each branch ends with a tail-recursive call.
 > [...]
 > What bugs me is having to list all the variables in the make_line_rec
 > call.  In reality, this function is just a while loop, and each time
 > through the loop one of a set of local variables (Acc, X1, Y1, X2, Y2)
 > is updated.

I usually start by looking for a wider context (more than one function)
where a set of parameters can be abstracted out into a record, like
Rich Beerman suggested. Things that are accessed or updated in every
iteration of a loop, I'd try to keep in separate parameters for efficiency.

In your example, the shape of the final result suggests this solution:

-record(line, {acc, x1, y1, x2, y2}).

make_line_rec(Tags, B, OtherStuff) ->
     make_line_rec(Tags, B, [], #line{}).

make_line_rec([{Tag,Ofs,Len}=Attr|T], B, Acc, L) ->
   case Tag of
      x1 -> make_line_rec(T, B, Acc, L#line{x1 = parse_units(B, Ofs, Len)});
      y1 -> make_line_rec(T, B, Acc, L#line{y1 = parse_units(B, Ofs, Len)});
      x2 -> make_line_rec(T, B, Acc, L#line{x2 = parse_units(B, Ofs, Len)});
      y2 -> make_line_rec(T, B, Acc, L#line{y2 = parse_units(B, Ofs, Len)});
      _ ->
         case is_attr(Tag) of
            true  -> make_line_rec(T, B, [get_attr(Attr, B)|Acc], L);
            false -> make_line_rec(T, B, Acc, L)
         end
   end;
make_line_rec([], _, Acc, L) -> L#line{acc = Acc}.

(Note that the Acc is kept in a parameter during the loop.) My guess would
be that with some small modifications, you could use the #line record in
other functions in the same module. Maybe you'll want to put the B parameter
in the record as well.

	/Richard




More information about the erlang-questions mailing list