Hacker News new | ask | show | jobs
by sly010 1749 days ago
> it does wrong thing without warning

It's not without warning, it's a well documented behavior.

Just think of slices as "immutable", "pass-by-value" data structures (with a relatively efficient implementation) and everything falls into place.

Mutating them in any way is actually a special case that you do only for performance reason (i.e. you can pre-allocate and fill if you know the size ahead of time) but - as always - you try to keep those abstracted away and to the minimum.

1 comments

> It's not without warning, it's a well documented behavior.

Ah yes, the usual excuse for it being fine that C APIs are completely broken and half of them can not be used correctly.

> Just think of slices as "immutable", "pass-by-value" data structures (with a relatively efficient implementation) and everything falls into place.

Except when they don't because `append` itself amortises allocations, which means if you treat slices as immutable and pass by value you will end up with slices sharing a backing array with leftover capacity and stomping on one another's data.

> Mutating them in any way is actually a special case that you do only for performance reason

Mutating them is literally what the normal Go API usage has you do. If you want to avoid mutating slices you need to write this abortion:

    s1 := append(append([]int(nil), s0...), item)
and if you do that in a loop, you get to feature on https://accidentallyquadratic.tumblr.com
Ok, I think I just understood the problem. The following would cause a problem:

   s0 := append([]string{}, "zoo")
   sa := append(s0, "foo")
   sb := append(s0, "bar") // overwrites sa[1]
Go is truly unique in this sense, and you could not actually treat go slices as immutable structures. Point taken.