New EEP draft: Pinning operator ^ in patterns

Raimo Niskanen raimo+erlang-questions@REDACTED
Wed Jan 20 15:12:29 CET 2021


On Wed, Jan 20, 2021 at 07:28:09PM +0530, Nalin Ranjan wrote:
> Hi,
> Call it curiosity, but I would also love to share something and look for a
> discussion around the following(and many people have noted this already).
> 
> " *So, if there is any proposal to put forth, in my view, it is to get rid
> of **variable shadowing*."
> 
> If Erlang *drops* support for "v*ariable shadowing*", will it not help
> address the "*emergence*" that we are discussing about?

I do not follow... Drop support for variable shadowing? Emergency?  

> 
> Even with *^-annotation* around, things are not addressed once and for all.
> The situation will only get avoided in the interim, but the likelihood of
> its reoccurrence still holds good.
> 
> As I could have a name whose first occurrence happens to be on line number
> 100, and all subsequent occurrences annotated with ^ in a defensive style.

All subsequent occurences in Patterns, that is.  Not allowed elsewhere.

> So far so good.Tomorrow I could embark on "Refactoring" fleet, and add some
> new code to the function around line 30-50, and endup naming one of my new
> variables to be the same as the one on line number 100. Situation,

You would get a warning about not using the pinning operator in the pattern
on line 100, if you use the warning.

/ Raimo Niskanen



> re-emerged. I need to go and attend these variables to deal with the
> situation. Or, I could embark on "Renaming" my variables to improve the
> "developer intent" for the sake of communication, even so I could lead to
> such a conflict. Even having the annotation capability around isn't helping
> too much for the problem which is being cited as the reason.
> 
> It's an *emergence*, and is owing to the way name<-> denotation association
> is handled in Erlang. Maybe we should try to deliberate more about the
> problem that the proposal is trying to address, and if there are options
> available which could keep Erlang closer to "minimalism" then I would
> prefer to go for that.
> 
> Thanks and Regards
> Nalin Ranjan
> 
> On Wed, Jan 20, 2021 at 6:16 PM Raimo Niskanen <
> raimo+erlang-questions@REDACTED> wrote:
> 
> > On Wed, Jan 20, 2021 at 01:47:12AM +0100, Chris Rempel wrote:
> > > Hello,
> > >
> > > > I agree about the beauty of Erlang's simplicity. For this particular
> > > > suggestion I, personally, feel that because Erlang "hides" if a
> > variable
> > > > occurence is a binding or a matching in the knowledge if the variable
> > has
> > > > occured before or not, it may be too simple because it is slightly
> > ambigous.
> > > >
> > > > Therefore I think that although annotating matches would make the
> > language
> > > > less simple it would improve clarity by making intention explicit.
> > > >
> > > > I can live without this, have so for the last 20 years, but I think
> > Erlang
> > > > would be a slightly better language with pinning than it is without it.
> > > >
> > > > / Raimo Niskanen, Erlang/OTP, Ericsson AB
> > >
> > > I find a different conclusion in this, with how I think when coding in
> > Erlang.
> > > Knowing a variable always has the same value after first use, whether
> > assigned
> > > or pattern match, and the value never can change, is such simple concept
> > to
> > > work with.
> >
> > The proposal does not change that property.
> >
> > >
> > > >From the EEP:
> > >
> > > f (X, Y) ->
> > >   case X of
> > >     {a, Y} -> {ok ,Y};
> > >     _ -> error
> > >   end.
> > >
> > > would no longer be valid (at some point in the distant future when
> > pinning is
> > > mandatory), and would have to be written:
> > >
> > > f (X, Y) ->
> > >   case X of
> > >     {a, ^Y} -> {ok ,Y};
> > >     _ -> error
> > >   end.
> > >
> > > yet today we can already write:
> > >
> > > f (X, Y) ->
> > >   case X of
> > >     {a, Y2} when Y2 =:= Y -> {ok ,Y2};
> > >     _ -> error
> > >   end.
> > >
> > > So, for those who want this EEP in order to be more explicit, why do you
> > not
> > > write your code in that third form and introduce an EEP requesting a
> > compiler
> >
> > I think that is too clumsy, just as it annoys me to have to do that when
> > defining fun()s:
> >     Y = value,
> >     F = fun (YY) when YY =:= Y -> Y end,
> >
> > > flag that you can use to generate a warning in the first form above, so
> > that
> > > you rewrite it in the third form. The second form flies in the face of
> > how I,
> > > and apparently many others, think in Erlang. The pinning operator is
> > > extraneous, and in fact determintal to that way of thinking.
> >
> > I have noticed the opinion that this breaks how they think about Erlang,
> > and above you mentioned the principle that the same variable has the same
> > value in all occurences.  I say that this proposal does not break that
> > principle.
> >
> > So I have a hard time understanding exactly what way to think it is that
> > the
> > pinning operator destroys.
> >
> >     Y = foo(),
> >     case bar() of
> >         {ok, ^Y} -> {ok, Y}
> >     end
> >
> > Y is the same variable and has the same value in all 3 occurences.
> > But I know for sure that the code did not crash at Y = foo(), because
> > Y can not have been previously bound.
> >
> >
> > >
> > > The good thing about this EEP is that it addresses variable shadowing.
> > It has
> > > always bugged me that variable shadowing was a thing in Erlang.
> > >
> > > f(X, Y) ->
> > >   F = fun
> > >     ({a, Y}) -> {ok, Y};
> > >     (_) -> error
> > >   end,
> > >   {F(X), Y}.
> > >
> > > That generates the shadow variable warning currently, and `f({a, 1}, 2)`
> > > returns `{{ok, 1}, 2}` which is just wrong as it breaks (in my view) the
> > rule
> > > that a variable value never changes.  And so pointlessly this must be
> > > rewritten like so:
> > >
> > > f(X, Y) ->
> > >   F = fun
> > >     ({a, Y2}) when Y2 =:= Y -> {ok, Y2};
> > >     (_) -> error
> > >   end,
> > >   {F(X), Y}.
> > >
> > > The pinning operator "fixes" this by allowing for:
> > >
> > > f(X, Y) ->
> > >   F = fun
> > >     ({a, ^Y}) -> {ok, Y};
> > >     (_) -> error
> > >   end,
> > >   {F(X), Y}.
> > >
> > > But in both cases, I have to explicitly say, hey Erlang, don't break
> > your own
> > > rule that a variable value never changes. To me this EEP is fixing the
> > problem
> > > in the wrong way.
> >
> > I do not see how the pinning operator breaks the rule that a variable's
> > value never changes.
> >
> > A variable's value never changes for all occurences of the variable in its
> > scope.  The variable's scope is all of the function after its first
> > occurence.
> >
> > When we get to fun()s we have a conflict of principles.  Should the
> > the same scoping rule apply to the fun() as to the surrounding function?
> >
> > Erlang has solved this with a pragmatic compromise (as often enough):
> > variables bound in a fun() are local to the fun().  But variables from the
> > outer scope that are referred to in a fun() are from the outer scope.  So
> > if it has the same name it is the one in the outer scope.  Except in the
> > fun() argument list.  Here variables are in general new ones so they are
> > local to the fun(), even if a different variable with the same name exists
> > in the outer scope.
> >
> > But a variable's value never changes within its scope.  Not today.
> > Not with this proposal.  The snag is; which variable do we mean?
> >
> > >
> > > So, if there is any proposal to put forth, in my view, it is to get rid
> > of
> > > variable shadowing.
> >
> > You are free to sketch on one; it does not have to be an EEP.
> >
> > A problem is that today variables in a fun() head shadows variables from
> > the outer scope, and the compiler warns about it.  If the behaviour should
> > be changed into not shadowing variables the compiler could not warn about
> > using a variable from the outer scope because it is now assumed that it is
> > the correct semantics.  If there was an annotation of the variables that
> > are bound instead of matched the compiler could tell the difference.  Such
> > an annotation would very much look like variable rebinding and could easily
> > be extended to exactly that.
> >
> > Another possibility would be to introduce some kind of let...end construct
> > to explicitly introduce variable scoping, which has been discussed before.
> >
> > There might, of course, be other possibilities.
> > I am not a language expert.
> >
> > >
> > > Also, already in this thread it is now being mentioned to have variable
> > > rebinding support. If this EEP erodes such a core tenant (in my view) of
> > > Erlang such that it leads to variable rebinding, it should be rejected
> > on that
> > > alone (in my view).
> >
> > I also do not want to get variable rebinding.  But this EEP should be
> > evaluated on its own merits and on the possibilities it offers that we
> > might want.
> >
> > >
> > > But the part of the EEP that just completely nullifies it is:
> > >
> > > > 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.
> > >
> > > You now have two variables named the same thing with different values. It
> > > breaks fundamental way of thinking in Erlang.  There is zero value in
> > allowing
> > > this. Use a different variable name.
> >
> > I agree that anyone that writes code like that deserves a good telling
> > off...
> >
> > I think the problem is in the variable shadowing, not in the pinning
> > operator.
> > Today we get a compiler warning when a variable in a fun() head shadows one
> > in the outer scope.  But other than that it is legal.
> >
> > We do not, however, get a warning when a variable is used in a fun() body
> > from the surrounding function since a fun() body has got the same scope as
> > the surrounding function, except for newly bound variables...  Accidentally
> > referring to a variable from outside the fun() is a problem.
> >
> > With the pinning operator it becomes possible to explicitly refer to the
> > outer scope and thereby possible to warn for referring to the containing
> > function without being explicit, making the fun() more a real variable
> > scope.
> >
> > >
> > > The EEP Rationale section is likewise problematic, but copying it here
> > and
> > > responding to each point is tiresome.
> >
> > That was some handwaving.  You are stating that it is problematic without
> > explaining why.  Not very constructive.
> >
> > >
> > > So, I'd like to propose that any EEP added to
> > https://github.com/erlang/eep/
> > > is done in a PR and left open for reviews/comments on the PR for a
> > period of
> > > time. There is much in the EEP that I would comment on, line by line.
> >
> > That is an interesting suggestion.  EEP 1 states that after an EEP has been
> > accepted (not approved) it should try to get community support, but it does
> > not say how.
> >
> > The current situation where this EEP is discussed in eeps@REDACTED,
> > erlang-questions@REDACTED, and in the PR for the reference
> > implementation
> > is not good.
> >
> > Having discussions about the EEP before submission (and after(?)) in a pull
> > request on the eep repository on GitHub sounds like a good step, except for
> > the ones that do not have accounts on GitHub, and it would drive us further
> > into the GitHub (/Microsoft) hands, which may be politically sensitive.
> >
> > >
> > > There has been concern on the list that this discussion has not remained
> > > technical and on point to the value of the EEP, and I would suggest the
> > fault
> > > lies in the tool being used to elicit feedback (e-mail). That concern
> > would be
> > > addressed by allowing people to comment line by line on the EEP and
> > discuss
> > > the specific points of the EEP in the PR itself. And we can avoid blame
> > being
> > > thrown around about people having or not having read the EEP.
> >
> > A very valid point.  I also think GitHub Pull Requests offer better
> > possibilities for discussion around details.
> >
> > >
> > > Regards,
> > >
> > > Chris
> >
> > --
> >
> > / Raimo Niskanen, Erlang/OTP, Ericsson AB
> >

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


More information about the erlang-questions mailing list