-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: syntax fix for := 'shadow variable' problem #30163
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
Comments
I like this proposal a lot. I understand you're not massively attached to that syntax, what about appending or prepending a, +b = foo() a, b+ = foo() |
Similar to this? #377 (comment) BTW, maybe it is not a big problem if the rules are defined clearly. func f() {
var a = []int{1, 2, 3}
{
a', a[1] = map[int]int{}, 999 // Which variable the second a represents?
// It would be better to represent the old one,
// but may bring a little confusions.
fmt.Println(a) // map[] or map[1:999]?
}
fmt.Println(a) // [1 2 3] or [1 999 3]?
} |
@sam3d I lean towards @go101 I'd say that's a niche enough scenario that simultaneous declaration and use in different targets of the same assignment should just be a compilation error. Can you think of any idioms where lack of some allowance would be missed? |
A compilation error? So do you think the second Could you clarify which ones of the following var a = []int{1, 2, 3}
{
a[1], a', a[1] = a[0], []int{7. 8. 9}, a[0]
} |
An alternative fix for the example problem in the proposal which fixes the typing problem in some circumstances but not the verbosity issue is to purposefully use a third variable: var a int
{
tmp, b := example()
a = tmp
} |
Please don't do that, don't bring Rust's crap syntax into go. |
EDIT: sorry, I didn't realize the issue was closed. This proposal is just another variation of those in issue #377 (some of them are 8 years old), and the discussion should probably take place there. And yes, I'm totally in favor of a per-variable short declaration syntax, I already commented here. @go101 my code rewriter turns each left hand side element into its own statement in order, so: var a = []int{1, 2, 3}
var b = []int{1, 2, 3}
{
:a, a[1] = map[int]int{}, 999
fmt.Println(a) // map[1:999]
b[1], :b = 999, map[int]int{}
fmt.Println(b) // map[]
}
fmt.Println(a) // [1 2 3]
fmt.Println(b) // [1 999 3] @DeedleFake I used the temporary variable solution for years (with subsequent assignments on the same line for clarity, but var a int
{
A, b := example(); a = A
} |
@OneOfOne I don't see how my suggestion is like Rust @go101 I'm saying you just have to pick a different name for the new variable: var a = []int{1, 2, 3}
{
// a[1], a', a[1] = a[0], []int{7. 8. 9}, a[0] // compile error
a[1], b', a[1] = a[0], []int{7. 8. 9}, a[0] // ok
a' = b
} Come to think of it, I'm not happy that Go allows redeclaration of a variable from outer scope that has already been used in this scope: a := 3
{
foo(a) // shouldn't be able to use 'a' of outer scope here
a := 5 // because we redeclare it later in this scope
foo(a)
} This seems error-prone to me as well, but it's too late to change this. |
Problem
The
:=
syntax is error-prone when dealing with multiple targets and variables of enclosing scope:Not only is the fix verbose, it defeats a nicety of inferred typing that it often spares us from having to remember precise return type(s), e.g. whether a returned type is a pointer or not:
Normally, Go disallows redeclarations, but it makes an exception for the
:=
syntax, such that we can't look at an:=
assignment and know for sure which of the target variables are being declared:Another problem is that we can't mix 'name' targets and 'non-name' targets:
Proposal
A syntax that marks individual targets of assignment as new variables. Let's say for now we'll use
'
as a suffix marker:We wouldn't remove the existing := syntax, of course, but in time its use would be considered non-standard style.
With this marking syntax, I don't see a good reason to disallow mixing in non-name targets:
It would also be nice if we could optionally specify types of one or more of the newly declared target variables to make them different from the corresponding return type:
As a last little bonus, perhaps type casts could be allowed on assignment targets:
I think these syntax choices are compatible with the existing grammar, but regardless, I'm not strongly attached to this exact syntax.
The text was updated successfully, but these errors were encountered: