Order Evaluation in List Comprehension

Claes Wikstrom <>
Sat Dec 19 00:42:28 CET 1998



Ben Hyde writes:
 > 
 > So is this good or bad? - ben
 > 
 > ----
 >   -module(hack).
 >   -export(black_box/1]).
 >   black_box(X) -> [ begin io:format("~p\n", [E]), E end || E <- X ].
 > ----
 >   
 >   ()28>c(hack)
 >   {ok,hack}
 >   ()29>hack:black_box([1,2,3,4]).
 >   4
 >   3
 >   2
 >   1
 >   [1,2,3,4]
 >   ()30> [begin io:format("~p\n", [E]), E end || E <- [1,2,3]].
 >   1
 >   2
 >   3
 >   [1,2,3]
 >   ()31> 
 > 


Well it teaches us to write code with side effects that is not
dependent on the evaluation order of arguments. 
Whenever we have side effects (such as messages or io) it is
always a good idea to make it clear that one expression is evaluated 
before or after another.

In this case you are running compiled code in the first case and
erl_eval.erl (The interpreter in the second) and they are two 
implementations of the same thing that happen to have different
evaluation order on lists. I.e the interpreter evals as
eval([H|T]) ->
   eval(H),
   eval(T).

whereas the compiler will lay out code that evaluates the tail first.


So, to answer you question: It is bad, sort of. We should have a fixed 
evaluation order and for lists it ought to be head first, tail last.

We also have things like tuples:

{io:format("a", []), io:format("b",[])}.


and function calls:

funky:foo(io:format("a", []), io:format("b",[]).

In the long lengthy dry dry dry specification doc at www.erlang.org we
have decided that in the next major release we shall have fixed
and decided evaluation order.

This has never been an issue for me personally since if I want to have
an explicit order on evaluation, I always write my code in such away
that the eval order is clear.

Cheers

/klacke





More information about the erlang-questions mailing list