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