New EEP draft: Pinning operator ^ in patterns

Raimo Niskanen raimo+eeps@REDACTED
Thu Jan 14 16:49:28 CET 2021


On Thu, Dec 24, 2020 at 04:05:12PM -0500, Fred Hebert wrote:
> On 12/24, Richard Carlsson wrote:
> >In this case, there is no new binding of `Y`, and the use of `Y` in
> >the fun clause body refers to the function parameter.  But it is also
> >possible to combine pinning and shadowing in the same pattern:
> >
> >    f(X, Y) ->
> >        F = fun ({a, ^Y, Y})  -> {ok, Y};
> >                (_) -> error
> >            end,
> >        F(X).
> >
> >In this case, the pinned field refers to the value of the function
> >function parameter, but there is also a new shadowing binding of `Y`
> >to the third field of the tuple.  The use in the fun clause body now
> >refers to the shadowing instance.
> >
> >Generator patterns in list comprehensions or binary comprehensions
> >follow the same rules as fun clause heads, so with pinning we can for
> >example write the following code:
> >
> >    f(X, Y) ->
> >        [{b, Y} || {a, ^Y, Y} <- X].
> >
> >where the `Y` in `{b, Y}` is the shadowing instance bound to the third
> >element of the pattern tuple.
> >
> 
> I don't understand the rationale here. If ^Y and Y are distinct in these 
> patterns, they should be named differently. It sounds unsafe to let the 
> values diverge.  The rationale in fact tries to expand on it there:

I think the EEP would benefit from rephrasing this not as a feature, but rather
as an example to explain the semantics.  If ^Y and Y are distinct a sensible
programmer would give them different names.  So the examples in the EEP
should also do that, except when explaining what should happen if you
actually use both ^Y and Y.

/ Raimo Niskanen


> 
> >Furthermore, in the odd case that the pattern would both need to
> >access the surrounding definition of `Y` as well as introduce a new
> >shadowing binding, this can be easily written using pinning:
> >
> >    f(X, Y) ->
> >        F = fun ({a, ^Y, Y})  -> {ok, Y};
> >                (_) -> error
> >            end,
> >        F(X).
> >
> >but in current Erlang, two separate temporary variables would be
> >required:
> >
> >    f(X, Y) ->
> >        OuterY = Y,
> >        F = fun ({a, Temp, Y}) when Temp =:= OuterY -> {ok, Y};
> >                (_) -> error
> >            end,
> >        F(X).
> >
> 
> But it still makes no sense why you would require Temp to be equal to Y 
> but only use the inner binding specifically. Semantically there is no 
> benefit to be had there, and this introduces a rebinding that isn't 
> required?
> 
> The one implementation detail that could have an impact there would be 
> based on the values of binaries references where there is specifically a 
> desire to use one more than the other.
> 
> I'm opposed only to this specific part of the RFC as not helping making 
> things clearer. Just name the variables differently and keep the 
> shadowing warning.
> _______________________________________________
> eeps mailing list
> eeps@REDACTED
> http://erlang.org/mailman/listinfo/eeps

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


More information about the eeps mailing list