> Go tells you very explicitly how it resizes slices by forcing you to write this:
No, what most readers intuit from that is that `append` performs no mutation and that this is fine:
s2 := append(s1, item)
because it looks very much like, say,
(def s2 (conj s1 item))
and often it will look like it works, especially at the smaller sizes, or if you never modify (or even use) s1.
Except it's absolutely not fine.
That's why other language separate slices and vectors and avoid confusing two objects which have different behaviours and uses even if their representation is very similar.
> It's only not fine if you some how assume that s2 and s1 will always refer to the same data.
It's not fine if you assume anything about the interaction of s1 and s2. It's not fine if you assume they do alias, it's not fine if you assume they don't.
There is, fundamentally, no situation in which that construct is anything other than a footgun. `append` should only ever be used with the same slice on the LHS and RHS[0], or a brand new slice object constructed for the occasion on the RHS.
> Go has a separate type for arrays, which is a value type
An array is neither a vector nor a slice.
The issue is that Go's slices serve as both a vector and an actual slice, and the union of these interfaces creates footguns which don't exist in either.
[0] IFF that RHS is a either a non-parameter local, or a pointer to a slice
No, what most readers intuit from that is that `append` performs no mutation and that this is fine:
because it looks very much like, say, and often it will look like it works, especially at the smaller sizes, or if you never modify (or even use) s1.Except it's absolutely not fine.
That's why other language separate slices and vectors and avoid confusing two objects which have different behaviours and uses even if their representation is very similar.