Of course you can give these operations names if you like, it's all up to you. In the form given you can account for every operation. It is easy to understand where the allocations are and where O(n) operations. There are no hidden temporaries which are quite common in other grammers.
I do often create stacks, dequeues, heaps, and other collections inline as needed. But I find this to be a lot cleaner then some other languages. It has the advantage of brevity and clarity. I can say I like this a million times over c++ template semantics, though I too am not a fan of boilerplate, so I can understand some people's resistance to this.
var stack []T
push := func(x T) {
stack = append(stack, x)
}
pop := func() T {
x := stack[len(stack)-1]
stack = stack[:len(stack)-1]
return x
}
push(value)
// ...
value = pop() slice[len(slice)-1]
The lack of a push and pop is a small inconvenience but it still disrupts my flow - not to mention adds unnecessary burden on testing to ensure I haven't cocked up something that should be elementary (and those kinds of errors are often a pain in the arse debug too).The latter isn't so much a productivity problem - I just think it looks ugly as sin. Which is why I sometimes add a .Last() method to any slice types I define where I need to read the last item regularly.
Lots of languages offer something akin to that. If not `[-1]` then something more OO like `.last`. Even the language I wrote supports it. This is why I made the complaint about Go.
> Also slice[0:-1] etc.
In fairness, Go can do that. You just omit the value for where you want the last (or first) element of the slice or array. eg
b := []byte("Hello, World")
world := b[7:]
(this would work with strings too but I'm using a byte to make it clear we're working with slices)edit: just for clarity I mean Go has the syntactic sugar for stating the start or end of a slice - rather than a negative number of elements from the end of the slice. My point being that there is already some syntactic sugar in specifying slices so it's a shame Go doesn't take that further.
I was actually referencing the 0 part and thus saying Go does already have some syntactic sugar when dealing with slices. ie you can do:
slice[5:] // slice[:len(slice)]
but not slice[5:-1] // slice[:len(slice)-1]
Which is a great pity.However I'll update my previous comment to make that clearer because I can totally understand how it reads confusingly.
#include <stack>
stack<T> st;
st.push(value);
auto value = st.pop();
I'm struggling to see what's a million times more appealing about the go.
Convince me?
I mean, I could decompose a lot of things into their more primitive representations from named functions, but when scanning a code review, I don’t want to miss a bug because someone transposed a colon in a slice operation.
It’s elegant in a minimalist way that all these things can be implemented in terms of slice operations, but why force everyone to reimplement these whenever they need to do something common that in other languages you just use the stdlib for and forget about?