Things like:
slices.Sort(s) // correct
slices.Compact(s) // incorrect
slices.Delete(s, ...) // incorrect
s := slices.Delete(s, ...) // incorrect if 's' is referenced again in the outer scope
s = slices.Delete(s, ...) // correct
All of those are solved by having functions like 'slices.Sort' take a '&mut' reference in rust speak, and having 'slices.Compact' and 'Delete' take an owned slice, and return a new owned slice.Even without going the whole 9 yards of the Rust memory model, something like the views in C++, or the java {Array,Linked}Lists containing references to objects and thus being resistant to re-alloc, or even plainly immutable list like in OCaml are all working and simple enough solutions to the issue.
I still can't wrap my mind around how supposedly experienced people like Pike & co. may have designed slices, then went ‶yep, that makes perfect sense for a robust, basic, widely used data structure to create our language around″, outside of a few toy programs.
By having this weird API on slices, they force you to be explicit on allocating new memory.
s := []int{}
for i := range 29754 {
s = append(s, i)
}
do you see explicit allocation of new memory? As far as I'm concerned that's not in any way more explicit than e.g. var s = new List();
foreach(var i in Enumerable.Range(0, 29754)) {
s.Add(i);
}I also fail to see how this would translate to
> make programmers mindful of the cost of allocating new space on array operations.
anyway. `append` is not taking in an allocator, reporting allocation failures, or reporting reallocations here. Like proper vectors, it's silently reallocating (and over-allocating) as needed.