bartblast

bartblast

Creator of Hologram

Anonymous functions equality comparison

Consider the following code:

iex> fn1 = fn x -> x end
#Function<42.3316493/1 in :erl_eval.expr/6>

iex> fn2 = fn x -> x end
#Function<42.3316493/1 in :erl_eval.expr/6>

iex> fn1 == fn2
false

iex> m = %{fn1 => 123}
%{#Function<42.3316493/1 in :erl_eval.expr/6> => 123}

iex> m[fn2]
nil

Is there some way to determine whether 2 anonymous functions are equal? By equal we can mean having the same underlying AST or being equivalent in some way.

Another related question:
what is “42.3316493/1” and is it possible to get this number programmatically somehow?

Marked As Solved

jhogberg

jhogberg

Erlang Core Team

Two anonymous functions are equal if they were created from the same definition (same fn ... statement) in the same module (same checksum), and have the exact same environment variables.

Funs defined in the shell satisfy the first two as long as their arity is the same, but differ in the latter as they’re interpreted by the shell which drags in a ton of stuff to their environment. If you want consistent results please try this with compiled modules instead.

Also Liked

jhogberg

jhogberg

Erlang Core Team

Yes.

Yes, because you’re consistently comparing different definitions. Different fn ... end statements yield different funs. If you were to compare the result of fun_1 to the result of another invocation of fun_1, they would compare equal.

LostKobrakai

LostKobrakai

Function.info can do that.

KristerV

KristerV

you sound like you know what you’re doing, but i feel like asking what you’re trying to accomplish anyway :slight_smile:

bartblast

bartblast

Creator of Hologram

By “environment variables” do you mean the variables captured in the closure of this anonymous function?

Using the following compiled code:

defmodule MyModule do
 def fun_1 do
   fn x -> x end
 end

 def fun_2 do
   fn x -> x end
 end

 def compare_1 do
   ((fn x -> x end) == (fn x -> x end)) |> IO.inspect()
 end

 def compare_2 do
   (fn x -> x end) |> Function.info() |> IO.inspect()
   (fn x -> x end) |> Function.info() |> IO.inspect()
   :ok
 end
end

iex -S mix:

iex> MyModule.fun_1() |> Function.info()
[
  pid: #PID<0.252.0>,
  module: MyModule,
  new_index: 0,
  new_uniq: <<93, 38, 53, 241, 226, 42, 107, 201, 80, 47, 228, 61, 192, 123,
    202, 1>>,
  index: 0,
  uniq: 48837039,
  name: :"-fun_1/0-fun-0-",
  arity: 1,
  env: [],
  type: :local
]
iex> MyModule.fun_2() |> Function.info()
[
  pid: #PID<0.252.0>,
  module: MyModule,
  new_index: 1,
  new_uniq: <<93, 38, 53, 241, 226, 42, 107, 201, 80, 47, 228, 61, 192, 123,
    202, 1>>,
  index: 1,
  uniq: 48837039,
  name: :"-fun_2/0-fun-0-",
  arity: 1,
  env: [],
  type: :local
]
iex> MyModule.compare_1()
false
iex> MyModule.compare_2()
[
  pid: #PID<0.251.0>,
  module: MyModule,
  new_index: 2,
  new_uniq: <<122, 234, 246, 244, 241, 108, 55, 10, 70, 250, 99, 174, 106, 44,
    101, 226>>,
  index: 2,
  uniq: 64444343,
  name: :"-compare_2/0-fun-0-",
  arity: 1,
  env: [],
  type: :local
]
[
  pid: #PID<0.251.0>,
  module: MyModule,
  new_index: 3,
  new_uniq: <<122, 234, 246, 244, 241, 108, 55, 10, 70, 250, 99, 174, 106, 44,
    101, 226>>,
  index: 3,
  uniq: 64444343,
  name: :"-compare_2/0-fun-1-",
  arity: 1,
  env: [],
  type: :local
]
:ok

Looks like the functions will always differ at least in new_index or index (?)

bartblast

bartblast

Creator of Hologram

I think I understand, thank you!

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
gazoon
I want to know absolute current module path. In python i could do that: os.path.abspath(__file__) Does elixir have anything similar?
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

Other popular topics Top

fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement