In cases when a slice:
- Is a field of a struct.
- Has a long name.
last_elem := my_struct.my_slice[len(my_struct.my_slice)-1]
or
last_idx := len(my_struct.my_slice)-1
last_elem := my_struct.my_slice[last_idx]
are less preferable to:
last_elem := my_struct.my_slice[-1]
These are both common occurrences if the last element of a slice is relevant to a program. I find the potential for off-by-one errors is increased and readability decreased by manually finding these indices.
Downsides
I understand this implies full implementation of negative indices for the entire slice, not just last element.
If it were up to me, the only way I would allow to do this is that any negative index is converted to its associated positive index, and then it works as it already does. This does lead to awkward oob cases like:
my_slice := make([]int, 10)
my_slice[-12]
The logic becomes somewhat circular here:
my_slice[-12] == my_slice[10-12] == my_slice[-2] == my_slice[10-2] == my_slice[8]
Above is internally consistent in a way but I imagine should have resulted in a bounds error. Just appreciating why this wouldn’t be added - though the fix for the above logic isn’t so complicated to warrant outright dismissal.
I can appreciate more the hesitation if this involves an index type change.
It seems Jai, Rust and Zig (not to mention C) also don’t have this feature, so I’m in the minority.
All said, I miss it and don’t believe it to be too fancy or too implicit.