New EEP draft: Pinning operator ^ in patterns

Nalin Ranjan ranjanified@REDACTED
Wed Jan 20 14:58:09 CET 2021


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?

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.
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,
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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20210120/d3c81d46/attachment.htm>


More information about the erlang-questions mailing list