Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

elixir

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?

like image 866
AndrewSwerlick Avatar asked Jun 16 '15 00:06

AndrewSwerlick


People also ask

How does anonymous function define Elixir?

Just as the name implies, an anonymous function has no name. As we saw in the Enum lesson, these are frequently passed to other functions. To define an anonymous function in Elixir we need the fn and end keywords. Within these we can define any number of parameters and function bodies separated by -> .

What is __ module __ In Elixir?

__MODULE__ is a compilation environment macros which is the current module name as an atom.

How do you define a function in Elixir?

An Elixir function is typically named, and is called a "named function". Functions are defined with the def keyword followed by a parameter list. A function also has a body containing the contents of the function. Like modules, the function body begins with the do keyword and ends with the end keyword.

What does |> mean in Elixir?

This is the pipe operator. From the linked docs: This operator introduces the expression on the left-hand side as the first argument to the function call on the right-hand side. Examples.


1 Answers

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>
like image 130
Patrick Oscity Avatar answered Sep 24 '22 19:09

Patrick Oscity