Re: New EEP draft: Pinning operator ^ in patterns
Raimo Niskanen <[email protected]>
| Newsgroups | gmane.comp.lang.erlang.general |
|---|---|
| Message-ID | <[email protected]> |
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 < > [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