[erlang-questions] Reassigning variables

Adam Lindberg adam@REDACTED
Thu Mar 19 14:30:58 CET 2009


You can even see a greater pattern here.

There is a state that is passed from function to function. Thus you have a series of functions transforming a data structure as they go.

f() ->
    foo(bar(baz(St0)))

It is then simple to insert new transformations in between. Just add another function call. If you need debugging in between, just debug the function calls. If you can't because they are too general, they're probably too general.

BUT, there is also another thing happening here. Each transformation can also return one or several variables saved for later use by later transformation. This can also be passed around by using a dictionary or a key-value list.

f() ->
    lists:foldl(fun(F, Acc) -> ?MODULE:F(Acc) end, {St0, []}, [foo, bar, baz]).

foo({St, Vars}) ->
    % Do stuff with state and vars
    {StNew, Vars ++ [{my_saved_var, Var}]}.
bar({St, Vars}) ->
    ...
    Something = proplists:get_value(my_saved_var, Vars, default)
    ...


It is then trivial to add another transformation function in the series, at any position. Just add another function name in the correct position in the function list and implement it in the module.

It is also easier to test each transformation independently from one another.

Just my two cents...

Cheers,
Adam

----- "Ulf Wiger" <ulf.wiger@REDACTED> wrote:

> Matthew Dempsky wrote:
> > 
> > Here's an actual block of code from the Erlang compiler:
> > 
> >     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,{atom,Lg,Name},[{var,Lg,Tname}]}, St4),
> >         {Guardc,St6} = lc_guard_tests(Gs, St5),     %These are
> always flat!
> >         {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 be a
> > function argument!
> >         Fc = function_clause([Arg], LA, {Name,1}),
> >         ....
> [...]
> > But, please, show me how you would write v3_core:lc_tq/5 without
> > numbered state variables without losing any readability.
> 
> So there's a pattern there, and there's actually a library
> function that might help to eliminate most of the numbered
> variable names.
> 
> thread(Fs, St) ->
>     lists:mapfoldl(fun(F,St1) -> F(St) end, St, Fs).
> 
> lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], Mc, St0) ->
>    {Gs,Qs1} = splitwith(fun is_guard_test/1, Qs0),
>    {[Name, Head, Tname], St1} =
>       thread([fun(St) -> new_fun_name("lc", St) end,
>               fun new_var/1,
>               fun new_var_name/1], St0),
>     ...
> 
> Whether it's more readable is perhaps a matter of
> taste. It ought to be easier to maintain though.
> 
> BR,
> Ulf W
> -- 
> Ulf Wiger
> CTO, Erlang Training & Consulting Ltd
> http://www.erlang-consulting.com
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions



More information about the erlang-questions mailing list