-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: Go 2: revisit explicit annotations in := #21303
Comments
Dup of #377? |
That thread covers a lot of potential changes to |
Before Go 1 := would only work if every name on the lhs had not been
declared in the current scope. This made it hard to write common code like
x, err := f()
//...
y, err := g()
This is not correct,
https://play.golang.org/p/aD8_f2r8M4
…On Fri, Aug 4, 2017 at 10:04 AM, Brad Fitzpatrick ***@***.***> wrote:
Dup of #377 <#377>?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#21303 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAcA9ajSza1u0_AHhT0L619SCUtrY4qks5sUmAjgaJpZM4OtIK3>
.
|
@davecheney that's Go 1 code. |
I'm not really sure this is that useful to be honest. |
Another alternative would be to annotate the new names instead of the old: that would make a For example, we could shift the colons from the x:, err: = f()
// …
y:, err = g() |
I don't really care about the syntax. There are other suggestions in #377 and the mailing list thread linked in there. I'm sure the Go team will pick something reasonable and pleasant in the face of all other constraints, if they decide to implement. I'll use I just want to be able to explicitly and concisely reuse variables from outer scopes without having to entirely and awkwardly rewrite the line with multiple Annotating new names rather than old names would make it easier to avoid accidental shadowing in the first place. I was thinking that another option would be to keep the default rules of I'd prefer "you always need to annotate" as it would mean not seeing an annotation had as much meaning as seeing an annotation, even though that would mean having to annotate more often. |
Then why not just use
|
I don't believe this is true, although I remember the discussion on changing the semantics of :=. From that previous discussion, ISTR favouring a syntax like this:
This doesn't avoid accidental shadowing though - I'm pretty sure you |
@as I don't care about the specific syntax used as long as there is some syntax with the desired semantics @rogpeppe I could easily be misremembering or confusing it with a comment from the Go team that "it worked like that but then we changed it". Maybe even another language entirely. I tried to find the thread to check before posting but could not so I crossed my fingers and posted. Oh well. At any rate, no I don't want to ban shadowing. Shadowing is good. But it can also be awkward and easy to shadow too much. The proposal is for some way to keep the nice bits of If that's the |
I would like it if shadowing an outer scope in the short declaration were banned. So, for example, this would be legal:
Because while But this would be illegal:
Because the inner I think something like a shadow ban is necessary to prevent the footgun of accidental shadowing. |
@carlmjohnson
|
I think that having to call the error |
How about ban short declarations except the ones in the first parts of control flow blocks? Short declarations bring too many confusions than their convenience. And they are much less readable than the long declarations. |
I'll go further: How about we have just one assignment syntax? Allow I don't care too much what the syntax is, but it bothers me that there are multiple syntaxes and I have to remember which one to use when. |
I confess that something about having two different declarations makes me itch just a little bit. If the short declaration is removed, the previous example becomes...
Or, to shadow by way of scoping,
However, effective redeclaration via shadowing would be disallowed:
I don't care for the added verbosity, and I'm rather fond of the |
Going off on a slight tangent, the verbosity above could be improved if we could use
|
I really can't imagine that Go 2 would remove either |
Commenting to add a cross-reference to #21114. |
Closing as dup of #377. |
@ianlancetaylor #377 is "locked and limited to collaborators." |
@jimmyfrasche Are you disagreeing that this should be closed as a dup? Still, I'll unlock #377 for now. |
No, it is a dup. I had assumed that by posting a summary in #377 that you were attempting to consolidate the discussion there which wouldn't work very well if no one could discuss. I figured you either forgot to unlock it or didn't notice it was locked and was trying to be helpful. |
@jimmyfrasche Thanks. I sincerely hope that #377 doesn't turn into a long-running discursive discussion. I don't think that is helpful. |
Before Go 1
:=
would only work if every name on the lhs had not been declared in the current scope. This made it hard to write common code likeEither
y
would require an explicit declaration withvar
or there would need to be an ugly workaround such asAmong other peccadilloes this meant copying a bit of valid code from one place to another could make it invalid and it would need to be rewritten.
This made
:=
much less useful than it could be so the current behavior of implicitly reusing existing names defined in the current scope was introduced and erroring out if none of the names were new.This made
:=
much more useful, but has made it too easy to shadow variables in outer scopes.When it was introduced, there was much discussion in the mailing list thread announcing the change (apologies but I cannot find a link) for a way to explicitly annotate the names to reuse such as
This was dismissed—if I recall correctly (again apologizes for not being able to track down the original thread)—because it would mean that copying a bit of valid code from one place to another could make it invalid, as annotations would need to be added or removed depending on the new context.
However, this is subtly true with the current behavior
:=
depending on the names involved and what is or is not in the current scope, leading to bugs caused by accidental shadowing that are hard to track down due to the implicit nature of what is shadowed when. This is particularly vexing with named returns.With explicit annotation it would still be possible to accidentally shadow a variable, but it would be easier to see what was happening at a glance and possibly easier to detect mechanically.
I think the idea of explicit annotation should be revisited for Go 2. I propose the following semantics
x, y, z := f()
follows the pre-Go 1 semantics—all names must be unbound in the current scopex, ^y, ^z := f()
reuses y and z as defined in the current scope or an outer but non-global scope†† making it incompatible with reusing variables in package global scope is a bit uneven but seems a wise safety precaution
This should be entirely
go fix
-able as the correct annotations to mirror the Go 1 semantics could be applied mechanically.The text was updated successfully, but these errors were encountered: