Skip to content
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: allow multiple variables with all assignment variants #30917

Closed
networkimprov opened this issue Mar 19, 2019 · 9 comments
Closed
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@networkimprov
Copy link

networkimprov commented Mar 19, 2019

Problem

Multiple variables/steps are allowed in some assignment cases, but not others.

// Allowed
a, b := 0, 1
a, b = a+1, b-1

// Disallowed
a++, b--
a += 2, b *= 2 // and -= /= etc

As a result we stutter when two counters are adjusted together:

for {
   i, err = r.Read(b)
   got, want = got+i, want-i
   ...
}

for a, z := 0, len(s)-1; a < z; a, z = a+1, z-1 { // common slice inversion
   s[a], s[z] = s[z], s[a]
}

Proposal

Revise the spec to one of:

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecList | Assignment | ShortVarDecl
IncDecList = IncDecStmt { "," IncDecStmt }


SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | AssignList | ShortVarDecl
AssignList = AssignCase { "," AssignCase }
AssignCase = IncDecStmt | Assignment

Allowing:

for {
   i, err = r.Read(b)
   got += i, want -= i
   ...
}

for a, z := 0, len(s)-1; a < z; a++, z-- {
   s[a], s[z] = s[z], s[a]
}

Thanks to @mingwho for raising this previously.

@gopherbot gopherbot added this to the Proposal milestone Mar 19, 2019
@gopherbot gopherbot added Proposal v2 A language change or incompatible library change LanguageChange labels Mar 19, 2019
@go101
Copy link

go101 commented Mar 19, 2019

how about

got, want += i, -i

a, z += 1, -1

@ianlancetaylor
Copy link
Contributor

I don't really understand your proposal summary.

a++ is not an assignment statement.

a += 2, b -= 2 is not an assignment statement, it's a pair of assignment statements.

So I'm not sure what you mean by "allow multiple variables in all assignment statements." It seems like you mean something else: in some cases it's OK to write multiple statements separated by a comma, as long as those statements are either assignment statements or increment/decrement statements.

Are you suggesting that any place that a simple statement may occur, it's OK to have a comma separated list of assignment statements or increment/decrement statements? For example, can I write

if a += 2, b -= 3; f(a, b) {}

Why are only assignment and increment/decrement statements permitted to be used in this way? Why not any simple statement (see SimpleStmt in the language spec)?

@networkimprov
Copy link
Author

networkimprov commented Mar 19, 2019

I called a++ an assignment because it's shorthand for a=a+1. But OK, I should have written "assignment and increment/decrement statements". [Now fixed.]

Are you suggesting that any place that a simple statement may occur, it's OK to have a comma separated list of assignment statements or increment/decrement statements?

Indeed.

Why not any simple statement ...?

I don't know a reason to comma-chain other kinds. I gave common-practice examples for the assignment/inc/decrement case.

PS. Why did you open with "I don't really understand" the summary, when you clearly did?

@networkimprov networkimprov changed the title proposal: Go 2: allow multiple variables with all assignment statements proposal: Go 2: allow multiple variables with all assignment variants Mar 19, 2019
@ianlancetaylor
Copy link
Contributor

PS. Why did you open with "I don't really understand" the summary, when you clearly did?

Because I tried to work out what you might have meant and made what appears to have been a good guess. Sometimes those guesses work, sometimes they don't.

I'm looking for a principled reason to decide which kinds of statements can be comma-chained. For example, if we do this, why not permit

    for c <- a, c <- b; ctx.Err() == nil; c <- x, c <- y { ... }

@networkimprov
Copy link
Author

networkimprov commented Mar 20, 2019

Is "let all assignment cases support multiple variables and/or steps" not a sufficient principle?

If we could write a, b <- 1, 2 then comma-chained channel sends would be reasonable :-)

@ianlancetaylor
Copy link
Contributor

Is "let all assignment cases support multiple variables and/or steps" not a sufficient principle?

I don't know what that means in terms of the language spec. The language spec doesn't have any concept of "assignment cases." It has concepts like SimpleStmt.

@networkimprov
Copy link
Author

Can we add a concept to the spec? e.g.

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | AssignList | ShortVarDecl
AssignList = AssignCase { "," AssignCase }
AssignCase = IncDecStmt | Assignment

@networkimprov
Copy link
Author

Alternatively to the above spec concept, here's one with only inc/dec chains, e.g. i++, j--

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecList | Assignment | ShortVarDecl
IncDecList = IncDecStmt { "," IncDecStmt }

I've added both to the proposal text.

@ianlancetaylor
Copy link
Contributor

This does not seem to address an important enough problem in the language. It doesn't add any functionality that we don't already have. In your examples, the only one that seems clearly simpler and easier to read is changing a, z = a+1, z-1 to a++, z-- in a for statement. Since ++ and -- is already syntactic sugar, this use seems to be piling sugar on sugar. This isn't worth the additional language complexity.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

4 participants