principle of least surprise

Robert Virding <>
Wed Nov 23 00:31:02 CET 2005


Martin Bjorklund wrote:

>After the obfuscation contest we now know that parentheses are
>important in guards...
>
>I have a datatype foo which is either an atom or a tuple of size 2.
>
>It would be nice with a macro to test if a certain value is a foo,
>e.g.
>
>  -define(is_foo(X), (is_atom(X) or (is_tuple(X) and (size(X) == 2)))).
>
>Then I could use this test in guards, 
>
>  f(X) when ?is_foo(X) -> yes;
>  f(X) -> no.
>
>Isn't this reasonable?  Anyone can read and understand this code.
>
>The problem is that this won't work; if I call f(foo) it will return
>no.  The reason is that all expressions in my guard will be evaluated,
>and that failure in a boolean expression will fail the guard which is
>interpreted as false. (and in this case size(foo) fails).
>  
>
Are you sure that this is the reason? When boolean guard expressions 
were added we defined a strict left to right evaluation jst so we could 
handle cases like this. One of my standard test cases was something like:

    when is_atom(X) or (is_integer(X) and (X + 5 < 6)) ->

(test cases are seldom reasonable). It worked then. Has the compiler 
been changed since then?

>So I tried some alternatives:
>
>  -define(is_foo(X), (atom(X) or (tuple(X) and (size(X) == 2)))).
>
>not that I thought that this would work, but it won't even compile.
>Why do we have atom/1 and is_atom/1???
>
>And I know that this one doesn't work.
>
>  -define(is_foo(X), (is_atom(X) orelse (is_tuple(X) andalso (size(X) == 2)))).
>
>Sigh.
>
>Maybe we shouldn't be allowed to write code like this?  No...
>
>My radical suggestion is:
>
>  o  make sure or,and  etc has precedence over ==,/= etc
>     (like orelse/andalso)
>  o  _remove_ orelse/andalso completely from the language
>     (what's the probability of that?)
>
>And then I think (size(X) == 2) should be false if X is not something
>you can do size on.  But that's probably out of the question.
>  
>
I quite honestly don't really see the problem with the precedences. 
Whatever is wrong with your macro it isn't the precedences. How do you 
envisage that (size(X) == 2) be false? What should size of something 
usizable return?

Since and/or behave as "normal" operators it was thought better to add 
new constructions with explicit left-to-right semantics rather than 
modify and/or. After a while you get into a horrible mess if you start 
special casing certain functions (operators are functions).

Robert



More information about the erlang-questions mailing list