erlang

Erlang -- How to convert a fun() object to a String


Is there a straightforward way to convert an Erlang fun to a string? A call to io_lib:format only prints the function reference, e.g. something like "#Fun<erl_eval.20.67289768>". For example, I'd like to be able to do this:

1> Fun = fun() -> atom_to_list('hello world') end.
2> FunStr = fun_to_str(Fun).
"fun() -> atom_to_list('hello world') end."

I'm looking for how to implement fun_to_str. In javascript, some interpreters have a .toSource() function that can be called on any object, including functions, that print their string representation. Any info is appreciated, thanks.


Solution

  • First, get the environment variables for the fun (which includes the abstract code):

    1> Fun = fun() -> atom_to_list('hello world') end.
    #Fun<erl_eval.43.39164016>
    2> {env, [{_, _, _, _, _, Abs}]} = erlang:fun_info(Fun, env).
    {env,[{{1,7},
           [],
           {eval,#Fun<shell.23.46532814>},
           {value,#Fun<shell.5.46532814>},
           #{},
           [{clause,{1,10},
                    [],[],
                    [{call,{1,16},
                           {atom,{1,16},atom_to_list},
                           [{atom,{1,29},'hello world'}]}]}]}]}
    

    Pretty print the abstract code using erl_pp:

    3> io:format("~s~n", [erl_pp:expr({'fun', 1, {clauses, Abs}})]).
    fun() ->
           atom_to_list('hello world')
    end
    

    (You have to add {'fun', 1, {clauses, ...}} around it to make it a complete Erlang expression)