When debugging a module (e.g. foo
) with list comprehensions temporary function names e.g.
foo:'-loop/4-lc$^2/1-3-'
can be found in trace output or error messages. If many list comprehensions are in a module its often hard to find out which one is running.
How can the function name be interpreted?
What are the meaning of the call parameters of these functions?
What is the meaning of the return value?
The fields can be described as follows:
foo:'-loop/4-lc$^2/1-3-'
^ ^ ^ ^ ^ ^ ^
1 2 3 4 5 6 7
lc
= list generator in a list comprehension, blc
= binary generator in a list comprehension, lbc
= list generator in a binary comprehension, fun
= fun)Open questions: what is the meaning of the parameters and return values of these functions?
Just stumbled on this answer by Robert Virding to the same question on the erlang-questions Mailinglist.
The code which creates these names is spread among many modules: sys_pre_expand
for funs; v3_core
for functions created for comprehensions; and v3_kernel
which adds more when lambda lifting the functions. The goal of all this is to create "unique" function names which also give some indication of why the functions were created and why.
In sys_pre_expand.erl
there is code fore creating function names for funs:
%% new_fun_name(State) -> {FunName,State}.
new_fun_name(#expand{func=F,arity=A,fcount=I}=St) ->
Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(A)
++ "-fun-" ++ integer_to_list(I) ++ "-",
{list_to_atom(Name),St#expand{fcount=I+1}}.
These names are passed on and expanded in a later pass (v3_kernel).
From the compilers v3_core.erl
:
%% new_fun_name(Type, State) -> {FunName,State}.
new_fun_name(Type, #core{fcount=C}=St) ->
{list_to_atom(Type ++ "$^" ++ integer_to_list(C)),St#core{fcount=C+1}}.
So this accounts for the "lc$^2" (parts 4 and 5) in the example. When looking at the places where it is used the possible values for part 4 can be deduced: lc
, blc
and lbc
.
In v3_kernel.erl
is the next phase when these functions are lambda lifted:
%% new_fun_name(Type, State) -> {FunName,State}.
new_fun_name(Type, #kern{func={F,Arity},fcount=C}=St) ->
Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(Arity) ++
"-" ++ Type ++ "-" ++ integer_to_list(C) ++ "-",
{list_to_atom(Name),St#kern{fcount=C+1}}.
This accounts for -loop/4-
(parts 2 and 3) and -3-
(part 7). Part 6 is added in the call to this new_fun_name/2
.
(This post is a community wiki, please add the other entries if you know what they mean)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With