Каково число, которое появляется после определения анонимной функции в эликсире?

Когда вы определяете анонимную функцию в elixir, вы получаете такой результат.

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

Что я заметил, так это то, что число основано на арности функции. Таким образом, функция 1 arg всегда

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

Две функции arg всегда

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

Функция трех аргументов всегда

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

Каково количество возвращаемых чисел и как оно получается?

Ответы

Ответ 1

Число состоит из индекса и уникального имени функции, которые генерируются компилятором. Взгляните на реализацию протокола проверки для функций. Он содержит этот отрывок:

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

где fun_info относится к результату предыдущего вызова :erlang.fun_info. Это свободно переводится на следующий псевдокод, где все интерполированные значения относятся к элементам fun_info:

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

Как вы правильно заметили, часть после / указывает на арность. module и name покажет вам, где была определена функция. new_index является указателем на таблицу функций модуля, а uniq является хэш-значением модуля, сгенерированного компилятором. Когда вы вызываете :erlang.fun_info для функции, вы сможете распознать значения из строки проверки:

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: [...]]

Значение uniq и индекс, взятые вместе, дают возможность однозначно идентифицировать анонимную функцию. Имейте в виду, что внутри iex эти предположительно уникальные значения будут очень похожими для всех создаваемых вами функций, но когда код "правильно" скомпилирован, они будут уникальными. Рассмотрим следующий сеанс iex:

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>

Теперь сравним это с запуском следующего файла с 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>