[erlang-questions] An old topic revisited

ok@REDACTED ok@REDACTED
Sun Jun 18 08:37:59 CEST 2017


Some time ago we had a thread about OR-patterns,
where amongst other things,
  pattern ::= ... | or_pattern
  or_pattern ::= pattern '|' pattern

A|B matches X if A matches X or B matches X,
A and B must bind the same variables.

The argument was made that it is painfully common
to have functions or cases with duplicate bodies
forced by matching different patterns.  As a
trivial example, take

f(ok | {info,_}, State) -> g(State);
f({warning,E} | {fatal,E}, State) -> crash(E, State).

At the time I pointed out that this could be done using
abstract patterns, quite easily.  (So why don't we have
abstract patterns yet hint hint.)

The same question came up recently in the Haskell
mailing list, for the same kind of reason.

It occurred to me to try the feature.
SML/NJ has OR-patterns.  So consider

fun f ((1,_)|(_,1)) ... ((n,_)|(_,n)) (0,0) = true
  | f       _       ...       _         _   = false
fun g () = f (1,1) ... (n,n) (1,1)

Now the smlnj compiler is normally pretty quick.
And I thought it might be quick on this.
What I really wanted was to measure how long it took
to run, for different values of n.
But I started with n=20, and so far, the compiler
has taken 24 minutes on a 3.2 GHz machine with no
end in sight.

In contrast, using view patterns in Haskell
(the Haskell equivalent of abstract patterns),

ok n (x,_) | x == n = True
ok n (_,x) | x == n = True
ok _ (_,_)          = False

f (ok 1 -> True) ... (ok n -> True) (0,0) = True
f       _                  _          _   = False

g () = f (1,1) ... (n,n) (1,1)

loads into ghci very fast, and g () runs faster.







More information about the erlang-questions mailing list