[eeps] EEP XXX: Pattern-test operator

Richard O'Keefe ok@REDACTED
Fri Apr 13 02:46:47 CEST 2012


On 13/04/2012, at 11:51 AM, Erik Søe Sørensen wrote:

> <EEP-pattern_test_operator.md>

(0) Congratulations and thanks for providing a reference
    implementation.

(1) PLEASE don't take the binary ~ operator; we need
    that for frames, and we need frames URGENTLY.
    The use of "~" is indeed backwards compatible
    with respect to existing _code_ but not with
    respect to existing _EEPS_.

(2) I don't understand why it is not sufficient to
    allow <pattern> = <guard expression> as a guard
    expression.  That would be a simple change that
    would increase the simplicity of the language
    by removing a constraint; this change makes the
    language *more* complex.

    The argument near the end I find unconvincing in
    the extreme: = isn't *supposed* to return booleans,
    and guards should never have had 'and' 'or' 'andalso'
    or 'orelse' in the first place but should have nested
    the existing ',' and ';'.  Guard tests drive control
    NOT by returning true or false but by SUCCEEDING or
    FAILING, and that's *exactly* what = does.

    It is already a readability problem that = can appear
    deeply nested inside expressions, and the proposed
    inverted ~ worsens this amazingly:  not only may
    bindings be hidden deep inside surprising places,
    they may be hidden in two opposing orders with
    subtly different semantics.

(3) Since we have the syntax <pattern> = <expression>,
    requiring <expression> ~ <pattern> is very nearly
    unforgivable.  The EEP confused me enormously
    until I got my head around this inversion.

(4) case ... of
      X  when  X ~ {ok,A}; X ~ [okay,A} -> ...A...
    end

    In "[okay,A}", is "[" a typo for "{"
    or is "}" a typo for "]"?  This can be handled
    by a proposal I _think_ there is an EEP for to
    allow

	case ...
	  of {ok,A}
           ; {okay,A} -> ... A ...
	end

    the generalisation being that
    	<pattern> [when <guard>]
    is replaced by
	<pattern> [when <guard>] {; <pattern> [when <guard>]}...

    That may have been one of the EEPs I could not write up
    because there is no serious definition of .md syntax and
    semantics.

    case E0 ~ P of true -> E1; false -> E2 end

    seems like a strange way to write

	case E0
	  of P -> E1
	   ; _ -> E2
	end

(5) The "bindings are only accessible" part is not specified
    precisely.  In particular, consider

	(X ~ {foo,A} orelse X ~ {bar,A} orelse X ~ {ugh,A})
	andalso ... A ...

    Is some binding for A accessible after andalso, and if
    not, why not?  If it were written

	case X
	  of {foo,A}
	   ; {bar,A}
	   ; {ugh,A} -> ... A ...
	end

    the variables available at the arrow would clearly and
    simply be the intersection of the variables available
    after each pattern/guard.

(6) The EEP has very few examples that cannot be done as well
    or better using Pattern = Guard_Expr in a guard and/or
    the generalised case, both of which make disjunction of
    pattern/guards readily expressible.  The main novelty
    seems to be "anything but this".

    For example,

	receive
	   X when (      F = {'$gen_cast',_} = X
	          orelse F = {'$gen_call',_} = X
		  orelse F = ok
		  ) andalso F = ok ->


    neatly handles the "not a {'$gen_cast',_} or {'$gen_call',_}"
    example, and all it needs is to allow Pattern = Expression in
    a context where people already expect it to be allowed.

    In general, I must say that I have learned over the painful
    years to loathe and dread "anything but <this>" matches in
    whatever language they are found.  If Erlang makes it hard
    to express such proven bug-breeder, all the better for
    Erlang.

    The lack of negative patterns is a positive BENEFIT of the
    way Erlang is now; sabotaging this aspect of Erlang would be
    done at our peril.


    All things considered, I think that the sharper the distinction
    between pattern/guards and expressions the better; it helps to
    keep Erlang readable in a way that anything-goes-anywhere doesn't.

(7) We keep on getting odd limited or dangerous proposals for
    things that are neatly and simply solved by abstract patterns.
    For example,

	#int_point(X, Y)
	    when is_integer(X), is_integer(Y)
	      -> {X, Y}.

	#two_int_points(X = #int_point(_,_),
                        Y = #int_point(_,_))
	      -> {X, Y}.

    Yes, the abstract patterns EEP notes that allowing patterns in
    guards is a prerequisite.  That mean we ALREADY have an EEP that
    proposes patterns in guards.  But that meant the existing =
    with the existing semantics; just a restriction removed.

    This new proposal is far more elaborate than the abstract
    patterns EEP requires, far more confusing, and far more dangerous.
    Once we have abstract patterns, there would be little or no
    reason to _use_ the inverted ~ in actual source code.

(8) The thing I don't get a feeling for is how _much_ of a problem
    this EEP solves.  When similar things have come up in the past
    I have asked for concrete examples, and have generally been
    able to show that it is possible to rewrite the real code in
    existing Erlang with good clarity without new features.
    (Or with abstract patterns as the only new feature.)





More information about the eeps mailing list