[eeps] EEP XXX: Pattern-test operator

Michael Truog mjtruog@REDACTED
Sat Apr 14 10:58:54 CEST 2012


I understand the order of execution remains deterministic.  My main concern centers on the binding of a local variable, since you are producing variables in a way that is currently impossible.  I also find it hard to argue for the benefits of producing local variables, as has been described, with pattern matching in guard expressions.  So, the benefits of such changes are eluding me.  There already exists the binding of local variables within the typical pattern matching expressions and we can depend on a guard expression never altering the program's state, except to determine a single return value that is boolean (I know there are problems mentioned in EEP 14, which I am choosing to ignore), used for either conditional branching within a case statement, augmenting the pattern matching that already exists there, or just providing the conditional branching that exists within an if statement.

The fact "=" is unable to bind a local variable within a guard statement is a very positive thing, to me, because of the assumptions you can make about guard statements, that would otherwise not be possible.  You know the scope of a guard statement is limited to itself, such that it just returns a boolean and no-more.

I understand that in what you described the scope of the locally bound variable is limited, as it would be in the currently supported uses (i.e., ways that we can currently bind local variables in patterns).  That doesn't seem to justify breaking the current barrier that exists within a guard statement, that prevents the binding of local variables within guard statements.

So, my concern is not about extra ordering constraints.  The potential for the proposal to eliminate optimization opportunities is not something that I would fully explore.  However, the most basic problem would be for register allocation, where guard expressions are currently very simple, so you can easily allocate all registers to evaluate a guard as quickly as possible, if you so choose, since you know all the guard expression contents is short-lived.  The guard statements are a closed system currently, that just returns one of two values, both atoms, 'true' and 'false'.  When you add local binding of variables to that, you introduce an unknown variable lifetime, which depends on context, making the code more complex and extending the scope of the guard's impact on the code.  I still see the local binding of the variable within the guard statement as a side-effect, despite the fact this is the lowest conceptual level where you would observe a side-effect (i.e., as a
variable binding).  The nature of a side-effect is where state in context A impacts state in context B.  When you consider a guard statement, and the proposal you are creating a unidirectional side-effect from a guard statement (context A) and the code it controls (context B).  The side-effect is not as dramatic as ets or the process dictionary, but it still breaks an intentional barrier that has existed.  I believe this absence of side-effects with guard statements is a very positive thing within the Erlang language that helps programmers make clear conditional statements that never get blurred within pattern matching statements, so that both can be combined, but always kept separate (in the current implementation).

So, when I say guards are self-contained, I mean that they are a closed-system, as described above.  I am sure that my verbalization is not formal when discussing these language features in the context of abstract programming language design.  I must also mention, I am not a decision-maker, just a practitioner that is severely bothered by guards becoming broken as described (i.e., the guards no longer guard, but let variables through).  The "~" operator reminds me of perl, so perhaps I have bad memories, but I really have trouble convincing myself that changes within your proposal are necessary (as they relate to binding local variables within guard statements), and I thought I should mention my concerns, since I would expect that others share my concerns.


On 04/14/2012 01:06 AM, Erik Søe Sørensen wrote:
> Binding local variables is not usually regarded as a side effect (in statically scoped languages such as Erlang).
> The "side effects reduce testability and optimation" concern, as I know it, is rooted in the concern that a piece of code may execute differently depending on which other parts of the code have executed earlier, and in what order.
> In this context, there is nothing to fear from the proposed change; the guarded body is executed if and only the guard succeeds, and the guard may bind the variable if and only if the whole guard succeeds. That is, there is still just one execution history leading up to the execution of a guarded body: now it's "pattern matches and pattern variables are bound; guard succeeds and guard variables are bound; body is executed".
> Code other than the guarded expression won't be affected, since the bound variables are only visible within that expression.
> Optimization opportunities could be reduced only to the extent that the new construct adds new evaluation order constraints. I do see one situation where that happens: when one guard expression in a (','-connected) guard binds a variable which is later used by another guard expression, as in "X~{ok,Y}, is_integer(Y)". In the implementation I shall have to make sure that guard expressions may still be reordered except when such dependencies actually exist.
>
> Just to be sure I understand your concern about the self-containedness of guards, when pattern have the same "problem": I figure you're thinking of guards in the context of 'if'-expressions?
> Per-clause variable bindings in 'if'-expressions certainly would be something new.
> (The language addition would make any 'case'-expressions expressible using 'if', whereas presently only the opposite is the case;
>   case E0 of
>     P1 when G1 -> E1;
>     ...
>   end
> would be equivalent to
>   Tmp = E0,
>   if Tmp ~ P1, G1 -> E1;
>      ...
>   end)
>
> /Erik
>
> Den 14. apr. 2012 03.42 skrev Michael Truog <mjtruog@REDACTED <mailto:mjtruog@REDACTED>>:
>
>     I see this change as making guards produce side effects because of the code like:
>
>         case ... of
>           X  when  X ~ {A,B}, X /= {0,0} -> A + B
>         end
>
>     (from "Binding semantics")
>     The variables A and B are leaking into the case result, so these variables are side-effects, right?  Otherwise, with the way Erlang is currently, guards are self-contained such that you can make assumptions about the code executed after a guard, saying "this code after this guard is not affected by the contents within the guard", and that statement helps as you read Erlang code, since it is functional and each statement returns a value... so guards currently have distinct separation from the code they control.  Your proposal seems to remove that separation, which should make source code more complex and will reduce the assumptions you can make about guard statements.  That is why I think it should reduce the testability of Erlang code and eliminate optimization opportunities.
>
>
>     On 04/13/2012 04:05 AM, Erik Søe Sørensen wrote:
>>     Allowing side-effects in guards would certainly not be in the Erlang spirit.  I wouldn't dare suggesting that :-)
>>     The left-hand expression in a pattern test expression which occurs within a guard is naturally(?) subject to the normal constraints for what is allowed in a guard.
>>     I should perhaps state that explicitly in the specification.
>>
>>     /Erik
>>
>>     Den 13. apr. 2012 02.54 skrev Michael Truog <mjtruog@REDACTED <mailto:mjtruog@REDACTED>>:
>>
>>         Your idea is interesting.  However, doesn't it ruin the simplicity of guards?  It seems as if this proposal would make guards generate side-effects which should impact both testability and optimization opportunities.  Isn't this a concern?
>>
>>
>>         On 04/12/2012 04:51 PM, Erik Søe Sørensen wrote:
>>>         Hello all -
>>>
>>>         Attached is a proposal to add to the Erlang language an operator which allows for pattern matching to be used in new contexts, in particular within guard expressions.
>>>
>>>         I hope the writeup to be in the expected format, as well as describing a sufficiently interesting idea.
>>>
>>>         Regards,
>>>         Erik Søe Sørensen
>>>
>>>           
>>>         _______________________________________________
>>>         eeps mailing list
>>>         eeps@REDACTED <mailto:eeps@REDACTED>
>>>         http://erlang.org/mailman/listinfo/eeps
>>
>>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/eeps/attachments/20120414/a84d6d5f/attachment.htm>


More information about the eeps mailing list