Re: New EEP draft: Pinning operator ^ in patterns
Nalin Ranjan <[email protected]>
| Newsgroups | gmane.comp.lang.erlang.general |
|---|---|
| Message-ID | <CACE+zkLf6CwKf2iHBHGukD5Lcq8F7y6j16P5mbc6D9qP1PTyOg@mail.gmail.com> |
On Wed, Jan 20, 2021 at 7:42 PM Raimo Niskanen < [email protected]> wrote: > 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? > Mentioned at so many occasions that it's a case of shadowing. And if so, maybe not having to shadow could help prevent the situation. No emergency, please. /Nalin Ranjan > > > > 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. > How about patterns inside nested scopes? > > > 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. > > True. I do follow warnings, and very comfortably fixes them in the code that I can control. But others' code is always a pain, and one could end up borrowing some.And third-party packages could just be another nightmare. > / 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 > > > Sorry about the below. I did read your replies, and so was intrigued to ask. /Nalin Ranjan > > On Wed, Jan 20, 2021 at 6:16 PM Raimo Niskanen < > > [email protected]> 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 [email protected], > > > [email protected], 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 >