10

What does it mean to compare functions in Erlang with the operators =:=,==,<,>,=<,>=?

I was playing around with the interpreter and got these results:

Eshell V5.9.2  (abort with ^G)
1> X = fun() -> {} end.
#Fun<erl_eval.20.82930912>
2> Y = fun() -> {} end.
#Fun<erl_eval.20.82930912>
3> 
3> {X == X, X =:= X}.
{true,true}
4> {X >= X, X =< X}.
{true,true}
5> {X > X, X < X}.
{false,false}
6> 
6> {X == Y, X =:= Y}.
{true,true}
7> {X >= Y, X =< Y}.
{true,true}
8> {X > Y, X < Y}.
{false,false}

This makes sense. It looks like it's comparing the abstract syntax tree of the two functions.

But in this session X and Y are defined the same once again but are different, also now X<Y?

Eshell V5.9.2  (abort with ^G)
1> X = fun() -> {} end.
#Fun<erl_eval.20.82930912>
2> 
2> {X == X, X =:= X}.
{true,true}
3> {X >= X, X =< X}.
{true,true}
4> {X > X, X < X}.
{false,false}
5> 
5> Y = fun() -> {} end.
#Fun<erl_eval.20.82930912>
6> 
6> {X == Y, X =:= Y}.
{false,false}
7> {X >= Y, X =< Y}.
{false,true}
8> {X > Y, X < Y}.
{false,true}

So it looks like it's not comparing the AST or any sort of unique references. Maybe it is comparing references, just some optimization is happening and X and Y get bound to the same reference? If there is some explanation for this, what happens across different VMs or different nodes?

2240
  • 1,547
  • 2
  • 12
  • 30
megazord
  • 3,210
  • 3
  • 23
  • 31

2 Answers2

4

The difference between the 2 evaluation in the shell comes from the blank line 6>. if you have a look at the fun using the function erlang:fun_info/1, you will see that in that case, the clause is stored with a different number (ie 2 instead of 1).

If you enter again the definition of Y (without a blank line) you will get a bad match, if you enter a blank line before, it is OK.

I think that this is a side effect of using the shell, but that the behavior is consistent within a program. Of course the meaning of > or < is not obvious for a fun, but == yes. A nice thing also is that the order of Erlang term is defined, so it is possible to sort a list of any term with predictable behavior:

number < atom < reference < fun < port < pid < tuple < list < bit string
Pascal
  • 13,977
  • 2
  • 24
  • 32
  • I guess `==` is only useful when comparing numbers. – halfelf Oct 26 '12 at 10:08
  • 3
    @halfelf No, `==` is useful for comparing anything and everything. You should just be aware of the semantics of comparison. I would not seriously compare functions, there are just too many ways in which "equal" functions can be unequal. For example if you expect it to compare ASTs then be aware that the AST contains line numbers. – rvirding Oct 26 '12 at 10:14
1

This behavior is different in shell and in compiled module. As for == and =:= operators in modules I am pretty sure that these operators return true iff:

  • Both functions are defined in the same place in code (isn't true in shell!)
  • Their effective closures are equal according to the respective (==/=:=) operator.

For instance with code

test(A, B) ->
  fun(C) -> {A, C} end.

the following shall hold:

> test(1, x) == test(1, y).
true.
> test(1, x) =:= test(1, y).
true.
> test(1, x) == test(1.0, y).
true.
> test(1, x) =:= test(1.0, y).
false.

Note that B does not belong to the closure of inner function therefore not influencing the comparison result.

radrow
  • 6,419
  • 4
  • 26
  • 53