Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don’t see how that is clearer than giving operations a name.

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?



There are pros and cons to be sure, but mainly I was just pointing out that the parent to my post was a bit of a straw man.

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()


In fairness, my biggest day to day pain point of using Go isn't the oft discussed lack of generics nor it's unpopular error returns. What bothers me the most when writing Go regularly is that I'm constantly having to reimplement basic functions for working with slices. The lack of a push or pop. Even selecting the last element of the slice via the following really becomes bothersome when you start dealing with multi-dimensional arrays:

  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.


Python supports slice[-1] for the last element... Pretty reasonable. Also slice[0:-1] etc. Swift also has a lot of array slice sugar, like array.last, array.endIndex, array.removeLast ... Obviously there is a trade-off to adding a lot of sugar to a language, in terms of learning the language, but leaving too little sugar in the language just leads to developers / library designers implementing the sugar themselves which leads to a whole mess of inconsistent code.


> Python supports slice[-1] for the last element... Pretty reasonable.

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.


In python slice[0:-1] drops the last element. To get the same effect in Go you need world := b[:len(b)-1]. The len() needs to be there (your example is a different case).


Yes, I was the one who made the comment about Go's lack of a -1 for slices in the first place. ;)

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.


For comparison the c++ looks like this:

    #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.


Marketing and hype are the only things it seems. I came to this conclusion after using golang at my current employer, and reading discussions by people online, as well as talking to them in person.


It just goes to show how golang is poorly designed as opposed to them just putting this stuff in a library, instead of polluting the global namespace with things like "copy" and "append".




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: