-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: Go 2: define += operator for appending to slices #29154
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
It would be weird to be able to |
If this proposal is approved, I would it could expand to support one of my proposal: #23905 For example:
The last line is equivalent to my |
It creates ambiguity that means I cannot tell the variable is a string or a slice of string when I see += sign. I don't think the current overhead is big. |
When we use
|
Perhaps this should be considered together with operator overloading. Without operator overloading, I think this particular use case isn't important enough to warrant making the language more complex. |
How about push(slice,value) which takes a reference to the slice instead, the perl way of doing these things i've always found a good way, adding push, unshift, shift and pop for slices would make everyone's lives easier. See here: https://perlmaven.com/manipulating-perl-arrays |
How do you tell right now if the variables are ints or strings? |
It's bad enough that |
The spec on
This would mean that in order to allow In terms allowing |
I think they are saying that if you have |
Sure, but I don't think that is a showstopper. If I have:
Is that a floating-point add or an integer add? How wide is that add? It depends on the type of What It is a bit weird to have |
Right, but
Not just non-commutative, but also non-associative. EDIT - this would also mean that |
That's already true for floats. I think it is understood that the RHS is evaluated before doing the |
I think that's the main thing that separates it. Being off by an ulp or so isn't too bad, but
We are currently talking about this kind of stuff, so it may be easy to realize what's going on in the code above. But seeing something like that in a random codebase somewhere would be extremely confusing. We already have |
Yes, it is best to guarantee the types of all operands are slices and their element types are identical
This proposal also avoids unnecessary resetting all elements to zeros in a |
I think this can also be achieved by allowing append to have multiple ... arguments foo = append(foo, l1..., l2...). Which doesn't add an alternative way to append slices but expands the existing way. #18605 I am also working on CL to allow make+copy not to do unnecessary zeroing https://go-review.googlesource.com/c/go/+/146719. |
@martisch I just made an alternative proposal for my original proposal. |
I don't think verbosity is really a problem in this case. I think the verbosity makes the code much more readable. Also what's all this talk about how this proposal eliminates a make+copy pattern? From what I understand this proposal is just syntactic sugar to convert |
While I don't interact with the Kotlin community much anymore, they define operator functions on their data structures. In my experience, mathematical operator functions on data structures are avoided because they make code less readable and are really more of a gimmick than anything else. Bracket notation on custom structures is commonly used, though. Just not addition/subtraction. |
If the copy(s) follow(s) right after the make it is not hard and I think covers all the cases that issues #29186 covers with |
There are definitely cases where compilers can optimize where a |
We don't have to have Currently Go operators operate on immutable operands; this proposal would change this property. That doesn't necessarily mean this is something we might not want to consider, but if we do consider it it should be in the broader context of operator overloading. This proposal just adds syntactic sugar for something we can already do in a more verbose way. |
Not a real proposal, but another way common append operations could be made more brief is if you didn't need to repeat the slice name twice. If append's first argument took a pointer to a slice instead of a slice, the pointer could mean to append to *ptr. In your example, var strs []string
strs = append(strs, "first") Would be: var strs []string
append(&strs, "first") And that's something you could do with the generics proposal yourself too. |
I actually like the separation of the return from the argument. It simplifies some neat little tricks, such as t := []int{1, 2, 3}
t = append(t[:2], t[1:]...)
t[1] = 0
// t: []int{1, 0, 2, 3} or t := []int{1, 2, 3}
t = append(t[:1], append([]int{0}, t[1:]...)...)
// t: []int{1, 0, 2, 3} for insertions and t := []int{1, 0, 2, 3}
t = append(t[:1], t[2:]...)
// t: []int{1, 2, 3} for deletions. Of course, I suppose it could just allow either syntax, but that just seems like more complication than it's worth. It doesn't need a second syntax. |
For strings the operator
+=
is defined to append one string to another. For slices, the same operator could be defined with the same meaning. This would shorten code that appends to a slice.Example
This could instead be written as:
Details
This pattern avoids the syntactic overhead of a function call and the repetition of the variable name. Most occurrences of the append function follow this pattern of appending a single value to a slice and then assigning to that same slice again.
The proposed operator would work only for appending a single element. Appending two or more elements would still require to use the
strs = append(strs, "first", "second")
form.Appending a slice to a slice might look like
strs += other...
, though this would require an extension of the Go syntax. Besides that, it would create an ambiguity for slices of interfaces. In such a case the+=
could either mean to append the slice as a single element or to append each element of the slice like in the...
operator. Therefore this proposal is only about defining the+=
operator to append a single element.The text was updated successfully, but these errors were encountered: