What is the number that shows up after you define an anonymous function in elixir?

417 Views Asked by At

When you define an anonymous function in elixir you get a result like this.

#Function<6.90072148/1 in :erl_eval.expr/5>

What I've noticed is that the number is based on the arity of the function. So a 1 arg function is always

#Function<6.90072148/1 in :erl_eval.expr/5>

A two arg function is always

#Function<12.90072148/2 in :erl_eval.expr/5>

A three arg function is always

#Function<18.90072148/3 in :erl_eval.expr/5>

What is the number that's being returned, and how is it being derived?

1

There are 1 best solutions below

2
On BEST ANSWER

The number consists of the index and a unique name of the function, which are generated by the compiler. Take a look at the implementation of the inspect protocol for functions. It contains this passage:

"#Function<#{uniq(fun_info)}/#{fun_info[:arity]} in " <>
  "#{Inspect.Atom.inspect(mod)}#{extract_name(fun_info[:name])}>"

where fun_info refers to the result of a previous call to :erlang.fun_info. This loosely translates to the following pseudo-code, where all interpolated values refer to elements of fun_info:

"#Function<#{new_index}.#{uniq}/#{arity} in #{module}.#{name}>"

As you have correctly observed, the part after the / indicates the arity. module and name show you where the function was defined. new_index is a pointer into the module's function table, and uniq is a hash value of the module generated by the compiler. When you invoke :erlang.fun_info for a function, you will be able to recognize the values from the inspect string:

iex> fun = fn x -> x end
#Function<6.90072148/1 in :erl_eval.expr/5>

iex> fun_info = :erlang.fun_info(fun)
[pid: #PID<0.58.0>,
 module: :erl_eval,
 new_index: 6,
 new_uniq: <<171, 204, ...>>,
 index: 6,
 uniq: 90072148,
 name: :"-expr/5-fun-4-",
 arity: 1,
 env: [...]]

The uniq value and the index taken together provide a way to uniquely identify an anonymous function. Be aware that inside iex these supposedly unique values will be very similar for all functions you create, but when the code is "properly" compiled, they will be unique. Consider the following iex session:

iex> fn -> end
#Function<20.90072148/0 in :erl_eval.expr/5>
iex> fn -> end
#Function<20.90072148/0 in :erl_eval.expr/5>
iex> fn -> end
#Function<20.90072148/0 in :erl_eval.expr/5>

Now compare that to running the following file with elixir fun.exs:

IO.inspect fn -> end
IO.inspect fn -> end
IO.inspect fn -> end

# this prints

#Function<0.120576197 in file:fun.exs>
#Function<1.120576197 in file:fun.exs>
#Function<2.120576197 in file:fun.exs>