Possible Go 2 proposal for built-in Remove method for Slices.

374 views
Skip to first unread message

Selahaddin Harmankaya

unread,
Feb 4, 2021, 6:55:36 PM2/4/21
to golang-nuts
Hi,
I wonder if there are any proposals for the Remove method for Slices, which removes an element from a Slice.
 
Since the status of the latest generics draft is `likely accepted` and it'd be possible to implement this with `generics`. I believe such an addition to language would alleviate the need to `loop + swap + resize` each time, and enhance the overall readability since there is a consensus.

This may seem trivial, but I want to highlight some examples from other langs just to further concretize:
arraylist.remove(object o) => java
list.remove(val) => python
array.remove(at: 0) => swift

I have looked for the proposals for Go 2 but couldn't find any regarding this issue.

There are obviously more things to consider, like whether the operation should keep the order.

I'd be very happy with your responses to this pseudo-proposal.

Uli Kunitz

unread,
Feb 4, 2021, 7:48:32 PM2/4/21
to golang-nuts
Hi,

You can always do a = append(a[:3], a[4:]...).  If you want to remove 2 elements a = append(a[3:], a[:5]....). You would need to call remove two times, which is slower and cumbersome.

I have rather have two functions like copy and append than a dozen that I have to learn. One of the Go Proverbs is "The bigger the interface the weaker the abstraction."

Greetings, Uli

Tyler Compton

unread,
Feb 4, 2021, 9:22:28 PM2/4/21
to Uli Kunitz, golang-nuts
You could imagine a `slices` standard library package that has a regular generic function called `slices.Remove` that removes one or a series of elements. This seems like a smart addition to me, as the current de-facto method isn't very expressive. I imagine this didn't exist before because adding a new built-in function has a far higher cost than adding a simple utility function to a package.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a7864041-2484-4664-9b2f-1578384defe0n%40googlegroups.com.

Brian Candler

unread,
Feb 5, 2021, 4:09:01 AM2/5/21
to golang-nuts
See: https://github.com/golang/go/wiki/SliceTricks#delete
(and lots of other neat tricks there).

There's no need to add new syntax or functions when the existing ones do the job.

Matthew Holiday

unread,
Feb 5, 2021, 8:45:35 AM2/5/21
to Brian Candler, golang-nuts
See also this graphical cheat sheet: https://ueokande.github.io/go-slice-tricks/

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.


--
Matt Holiday
Senior Gopher, Marketing Technologies

620 Eighth Avenue

New York, NY 10018

matthew...@nytimes.com

Fernando Meyer

unread,
Feb 5, 2021, 9:46:26 AM2/5/21
to golan...@googlegroups.com
I understand the pragmatism behind having or not features in the language and its standard library. But, almost all the golang projects I've worked with implement their own utility function to remove elements from a slice, sometimes with order in place, others not. Mostly always these home-brewed libraries ignore bounds-checking introducing runtime problems if the user is not careful enough.

That said, when a feature becomes a ubiquitous necessity across so many codebases, I believe it should be considered to have a standard implementation.

[]s
--
  Fernando Meyer
 

Ian Lance Taylor

unread,
Feb 5, 2021, 9:53:41 AM2/5/21
to Fernando Meyer, golang-nuts
On Fri, Feb 5, 2021 at 6:46 AM Fernando Meyer <f...@pobox.com> wrote:
I understand the pragmatism behind having or not features in the language and its standard library. But, almost all the golang projects I've worked with implement their own utility function to remove elements from a slice, sometimes with order in place, others not. Mostly always these home-brewed libraries ignore bounds-checking introducing runtime problems if the user is not careful enough.

That said, when a feature becomes a ubiquitous necessity across so many codebases, I believe it should be considered to have a standard implementation.

This seems like a clear case for using generics, so let's wait on this until we see whether the generics proposal is adopted and implemented.  I think it is preferable to use a general language mechanism than to add a special purpose function to the language.  See my notes about append at https://www.airs.com/blog/archives/559.

Ian

Jan Mercl

unread,
Feb 5, 2021, 9:55:25 AM2/5/21
to Fernando Meyer, golang-nuts
On Fri, Feb 5, 2021 at 3:46 PM Fernando Meyer <f...@pobox.com> wrote:

> I understand the pragmatism behind having or not features in the language and its standard library. But, almost all the golang projects I've worked with implement their own utility function to remove elements from a slice, sometimes with order in place, others not. Mostly always these home-brewed libraries ignore bounds-checking introducing runtime problems if the user is not careful enough.
>
> That said, when a feature becomes a ubiquitous necessity across so many codebases, I believe it should be considered to have a standard implementation.

There are two incompatible algorithms for removing an element from a
slice. One moves any remaining elements down, the other moves only the
last element in the place of the removed one.

Which one is the "standard implementation" and why?

The next question will be, why limit ourselves to removing always only
one element, why not generalize to N elements?

The next question will be, do we need to zero the now unused portion
of the slice? It matters sometimes a lot, but it's just overhead where
it does not.

Artur Vianna

unread,
Feb 5, 2021, 9:56:21 AM2/5/21
to Matthew Holiday, Brian Candler, golang-nuts
it may be useful to avoid repetition, for example if implementing stacks, you have to create the "pop(), push(), top()" before starting to code what you want.

Maybe there's place for this utility functions under the "container/" package (like "container/slice"), where you could do things like:

st := slice.New([]byte{})
st.Push(1)
b := st.Pop()
st.Queue(b)
b = st.Dequeue()

st.Add(2)
st.DeleteIndex(0)
st.Add(7)
st.DeleteItem(7)

etc

Wojciech S. Czarnecki

unread,
Feb 5, 2021, 9:33:02 PM2/5/21
to golan...@googlegroups.com
Dnia 2021-02-04, o godz. 00:30:57
Selahaddin Harmankaya <selahad...@gmail.com> napisał(a):

> There are obviously more things to consider

Slice is not an array, it is a _view_into_ an array. Many such views
into the same array may exist simultaneously.

A "remove element from _slice_" operation always must make a new array
and copy all elements that you intend to stay. Current idiom using append
will do this for you while being frank about costs.

See: https://blog.golang.org/slices-intro
and: https://www.digitalocean.com/community/tutorials/understanding-arrays-and-slices-in-go


Hope this helps,

--
Wojciech S. Czarnecki
<< ^oo^ >> OHIR-RIPE

Martin Schnabel

unread,
Feb 6, 2021, 6:25:38 AM2/6/21
to golan...@googlegroups.com


On 06.02.21 03:32, Wojciech S. Czarnecki wrote:
> Dnia 2021-02-04, o godz. 00:30:57
> Selahaddin Harmankaya <selahad...@gmail.com> napisał(a):
>
>> There are obviously more things to consider
>
> Slice is not an array, it is a _view_into_ an array. Many such views
> into the same array may exist simultaneously.
>
> A "remove element from _slice_" operation always must make a new array
> and copy all elements that you intend to stay. Current idiom using append
> will do this for you while being frank about costs.

Maybe I misunderstand what you wrote, but as long as the slice has
enough capacity the array will be reused and not not copied:

https://play.golang.org/p/sevpWixzw6V

Arnaud Delobelle

unread,
Feb 6, 2021, 6:37:09 AM2/6/21
to Martin Schnabel, golang-nuts
On Sat, 6 Feb 2021 at 11:25, Martin Schnabel <m...@mb0.org> wrote:
>
>
>
> On 06.02.21 03:32, Wojciech S. Czarnecki wrote:
> > Dnia 2021-02-04, o godz. 00:30:57
> > Selahaddin Harmankaya <selahad...@gmail.com> napisał(a):
> >
> >> There are obviously more things to consider
> >
> > Slice is not an array, it is a _view_into_ an array. Many such views
> > into the same array may exist simultaneously.
> >
> > A "remove element from _slice_" operation always must make a new array
> > and copy all elements that you intend to stay. Current idiom using append
> > will do this for you while being frank about costs.
>
> Maybe I misunderstand what you wrote, but as long as the slice has
> enough capacity the array will be reused and not not copied:
>
> https://play.golang.org/p/sevpWixzw6V
>

Yes, given this and e.g. https://play.golang.org/p/Dyh9Dzd-1zq , in my
opinion it's hard to argue against having slice manipulation
primitives with clearer semantics. Having generics will allow this
though!

--
Arnaud

Kevin Chadwick

unread,
Feb 6, 2021, 7:43:56 AM2/6/21
to golan...@googlegroups.com
>> >
>> > A "remove element from _slice_" operation always must make a new
>array
>> > and copy all elements that you intend to stay. Current idiom using
>append
>> > will do this for you while being frank about costs.
>>
>> Maybe I misunderstand what you wrote, but as long as the slice has
>> enough capacity the array will be reused and not not copied:
>>
>> https://play.golang.org/p/sevpWixzw6V
>>
>

Incidentally I've been wondering how this works for slices of strings and haven't found much on golang.org or via google yet. Are allocations still avoided for arbitrary sized strings?

Sean

unread,
Feb 6, 2021, 11:36:01 AM2/6/21
to golang-nuts
I think there is definitely a need for a built-in "remove" function for arrays and slice.
Everyone is writing their own implementation for this, it is both confusing and "x = append(a[:x], b[x:])" like blablabla is not readable.


5 Şubat 2021 Cuma tarihinde saat 02:55:36 UTC+3 itibarıyla selahad...@gmail.com şunları yazdı:

Jan Mercl

unread,
Feb 6, 2021, 1:24:56 PM2/6/21
to Sean, golang-nuts
On Sat, Feb 6, 2021 at 5:36 PM Sean <s.tolst...@gmail.com> wrote:

> I think there is definitely a need for a built-in "remove" function for arrays and slice.
> Everyone is writing their own implementation for this, it is both confusing and "x = append(a[:x], b[x:])" like blablabla is not readable.

Please define the semantics of "remove" operation. IINM, that has not
yet been done in this thread.

Note that "removes an element" of a slice is not an acceptable
specification. That's circular and useless.

The specification must define what happens to which elements of the
slice. Additionally it must be specified what are valid arguments of
"remove" and what will happen if they are not valid.

Axel Wagner

unread,
Feb 6, 2021, 2:02:26 PM2/6/21
to Jan Mercl, Sean, golang-nuts
FTR, I think even a library function that is defined as "the equivalent of `append(a[:i], a[j:]...)`" (for example) would provide value.
That being said, I also think having this discussion now seems pointless. Any of it will clearly not happen before generics land (or are rejected), which is still at least a year out, AIUI. And even then, it'll probably will be at least another go release or two to see how people use generics and evaluate the usefulness of it. So litigating the pros and cons of a package we can't even write for at least a year and won't have tangible data available to base a decision off of for another one seems futile to me.
YMMV, of course.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.

Jan Mercl

unread,
Feb 6, 2021, 3:16:24 PM2/6/21
to Axel Wagner, Sean, golang-nuts
On Sat, Feb 6, 2021 at 8:01 PM Axel Wagner
<axel.wa...@googlemail.com> wrote:

> FTR, I think even a library function that is defined as "the equivalent of `append(a[:i], a[j:]...)`" (for example) would provide value.

Yes, but IMO a net negative value. Many people will then mindlessly
just use this O(n) variant even though in many cases the O(1) version
could and should be used instead.

Also, note how easy it is to fall into the O(n^2) trap with this
definition of "remove".

Wojciech S. Czarnecki

unread,
Feb 6, 2021, 6:13:06 PM2/6/21
to golan...@googlegroups.com, Martin Schnabel
Dnia 2021-02-06, o godz. 12:24:59
Martin Schnabel <m...@mb0.org> napisał(a):

> > A "remove element from _slice_" operation always must make a new array
> > and copy all elements that you intend to stay. Current idiom using append
> > will do this for you while being frank about costs.

> Maybe I misunderstand what you wrote,

Uh, neither do I understand it now :) Apparently I shouldn't be replying to
the single line that grabbed my fading attention after too long a day; and
I certainly should not mindlessly pat "send" in the morning, too.
If I recall properly, my mind wandered near subtle fallacies surrounding slice
usage https://blog.allegro.tech/2017/07/golang-slices-gotcha.html

Nonetheless, I humbly apologize to whomever wasted time trying to guess
what I had on mind.

TC,
Reply all
Reply to author
Forward
0 new messages