# principle of least surprise

Richard A. O'Keefe <>
Thu Nov 24 00:36:36 CET 2005

```Martin Bjorklund <> wrote:
What't the point of having two different (three if you count ; and ,)
ways of saying and/or?

Given the existance of 'andalso' and 'orelse', we don't need 'and' or 'or'.
A style warning triggered whenever someone uses them would be a good idea.

E1 and E2 can always be rewritten as (T = E1, E2 andalso T),
E1 or  E2 can always be rewritten as (T = E1, E2 orelse T).

I don't advocate having 'two different ... ways of saying and/or';
my point is that 'andalso' and 'orelse' are not the ones to discard.

> Having a type that is either an atom or a pair?  Fine, no problems.
> It's easy enough to write functions
>
>     f({X,Y}) -> ...;
>     f(X) when atom(X) -> ... .

This isn't really useful if I have more than just a few functions
operating on this type - I would have to do

f({X,Y}) ->  ... g({X,Y}) ,...
f(X) when is_atom(X) ->  ... g(X) ,...

Why on earth would you do that?

You have the two clauses when and ONLY when you want to do something
DIFFERENT in each case.  In your example

f({X,Y}) -> ... g({X,Y}) ... .
f(X) when is_atom(X) -> ... g(X) ... .

you should have just the one clause,
f(X) - ... g(X) ... .

As long as bad data is caught before some side effect (externally visible
message send, change to the process dictionary, &c) takes place, it doesn't
matter (much) where it's detected.

The claim that you would have to do this "for all functions" is without
any warrant at all.
> Do I have to mention that abstract patterns could have solved the original
> problem with ease?  Maybe I do.

But you just said that what i tried to achieve was odd.  With your
abstract patterns I'm suddenly allowed to think in these odd ways?

I'm afraid so.  There _is_ actually a defensible reason for it, to do with
hot loading.  The idea is that if data accesses are done through abstract
patterns and a module is revised so that a datum holds more information or
has more cases, abstract patterns in the new version of the module can be
written so that they recognise the old data values as well as the new ones,
except where new data are involved.  But when used for generating data,
they would generate the new structures.  So you can upgrade a module
without dropping live data.

The downside of being able to do _that_ is that you can also do things that
are not quite so sensible.

```