Live data from Hacker News

Go 1.18

go.dev

431–440 of 614 posts

Re: Go 1.18

#431
post #298

Earlier quoted context omitted.

Hits the sweet spot for me between the one extreme of having to malloc/free everything myself and the other extreme where everything is immutable, garbage collected and you dont know what causes allocation. The former is a nightmare for security and productivity, the latter is a nightmare for performance.

Go can implicitly heap-allocate even a local variable if you e.g. capture it in a closure. This is actually more implicit than you get in Java or C#.

Java can decide to heap-allocate or not heap-allocate at runtime based on what optimizations the JIT has performed so far, and so it can change over the course of a program's run. I don't think you can get more implicit than that.

Re: Go 1.18

#432
post #71
post #67

For me the most puzzling aspect of Go is channels. Ada tried CSP (Concurrent Sequential Processes that Go channels are based on) in eighties and people quickly realized that it lead to bad performance and was unsuitable for a lot of useful cases. So Ada got standard mutexes and signals. So why CSP which does not allow to implement priority delivery or multicasting and makes cancelling much harder compared with normal…

I can never seem to understand why a GCed language has pointers, and makes you memorize when to use stack vs heap.

[deleted]

Re: Go 1.18

#433
post #4

WOOO! I have been using the RC at work lately, and I have to say: The generics implementation is quite nice, and RUTHLESSLY slashes boilerplate and copy-pasta. This is going to turn Golang from "that one boilerplate-y language without generics" into my favorite language. I've been using the https://github.com/samber/lo library, and it is very nice to be able to do "map/reduce/etc..." on golang structs. I would really…

So, I don't want to tear too much into someone's side project, but a lot of this is exactly what people are worried about.

As an example, let's take the `Chunk` function, since that's something I know I have three implementations that differ only in type in one project, pre-generics:

    result := make([][]T, 0, len(collection)/2+1)
    length := len(collection)
len(collection)/2? If you're splitting a list of size M into N chunks, you know exactly how many chunks you need a priori, and it's not M/2+1.

    for i := 0; i 
But worse: You allocated a whole new slice to store the chunk! What a waste.

But, you know, the real frustrating thing in the end is that it allocated anything at all. Chunking can also happen iteratively on the source slice:

    func [T any]([]T, int) (chunk []T, remaining []T)
And then it will be zero-alloc.

But, once you see this, you see we could write something that works on indices:

    func (len int, size int) (split int)
And get nearly the same effect, without any generics.

Go (See also my comments at https://news.ycombinator.com/item?id=29905908#29926708 - just because you have a generic type doesn't mean you should use it as much as possible, even if you do need to use it once.)

I'm happy to see generics in golang. It will simplify a ton of my higher-level code like REST endpoints, and be a minor boon to low-level code. But this library, as useful as some parts may be, is also a great example of why they're a dangerous tool.

Re: Go 1.18

#434
post #416
post #412

Earlier quoted context omitted.

Go has maps already. A set is just a map where the key and value are the same thing.

Sets tend to have methods like difference, union and intersection - with a map[T]bool, if you want to find the difference, union or intersection of 2 sets, you have to do all of that with much more verbose (and error prone) loops. Also, the type being a set carries a semantic meaning, with a map[T]bool it’s not obvious from the type alone that we only care about the keys, not the values.

> with a map[T]bool

This takes up unnecessary space—use map[T]struct{} instead, which also explains to anyone reading the code that the value isn't used.

Re: Go 1.18

#435
post #416
post #412

Earlier quoted context omitted.

Go has maps already. A set is just a map where the key and value are the same thing.

Sets tend to have methods like difference, union and intersection - with a map[T]bool, if you want to find the difference, union or intersection of 2 sets, you have to do all of that with much more verbose (and error prone) loops. Also, the type being a set carries a semantic meaning, with a map[T]bool it’s not obvious from the type alone that we only care about the keys, not the values.

You can also use a map[T]struct{}. I like bool better because of the default value behavior but struct{} is very clear and does not take extra memory.

Re: Go 1.18

#436

Earlier quoted context omitted.

This is really vague and unhelpful. I’m going to interpret this to mean you’re not interested in actually explaining the problem, sorry if I’m mistaken.

For what it’s worth, this is the read I’ve gotten from this thread as well. I’m not sure how else to interpret the parent’s remarks—his responses seem evasive rather than clarifying.

Yea I noticed that in your interactions with them too. Also while I’m here I want to compliment you on your articulations of the strengths of go throughout this comments section! They’ve been very well put/compelling and helped me understand better how to express the things I like about go in the face of its detractors, which is a constant struggle for me.

Re: Go 1.18

#437
post #418

Earlier quoted context omitted.

Why are new data structures worrying?

The downside is they’ll make Go code less uniform. Do you represent nullability with a nil-able pointer, or an option monad? To transform a list, do you loop over a slice, or map/flatMap/filter over a more functional data structure? etc. Pre-generics, Go has been a very limited language. On the downside it’s verbose and error-prone, on the upside it’s very uniform. I think generics will make it less verbose and error…

> Pre-generics, Go has been a very limited language. On the downside it’s verbose and error-prone, on the upside it’s very uniform.

Except that this kind of uniformity inherently tends to disappear in larger projects, to be replaced by increased complexity. Java was also designed to be a "simple" language, one trivially understandable by hordes of low-skilled code monkeys, and yet look at the added layers of complexity in many Java enterprise frameworks. More full-featured languages, when properly designed (especially, avoiding the feeping creaturitis of something like Scala), make it easier not harder to manage inherent complexity at a larger and larger scale of development. But Go is now basically stuck with its constrained feature set, and Go developers cannot easily avail themselves of these tools. This is why so many devs criticize this particular design goal; it's pretty much incoherent.

Re: Go 1.18

#438

Earlier quoted context omitted.

Generally direct refutation of a central point is a constructive argument. Here’s another example of direct refutation: You’ve given a strawman argument, specifically you’ve given one implementation which has abstracted the details (we don’t see the code for take, select and reduce). That’s just an arbitrary decision you’ve made, the equiv go example you could have posted might be: // idiomatic error handling elided…

> in the worst case we would have repeated definitions of these functions. Code that any junior developer will be able to safely reason about and change It's also code that many junior developers will forget to change in all the places when they fix a bug in one of them.

Yeah that’s what i was getting at with:

>> Code that has utterly obvious risks (you might introduce a differing behaviour in one implementation of Take() for example) - so obvious that it’s trivial to defend against with nothing more than generative testing.

Really obvious risks are usually easier to handle than more obscure ones.

Re: Go 1.18

#439

Earlier quoted context omitted.

The syntactic choice of using square brackets instead of angle brackets for generics appears to be due to optimising for parsing. User clarity is decreased to allow for code optimisation IMHO. From https://groups.google.com/g/golang-nuts/c/7t-Q2vt60J8 the following: Angle brackets require unbounded parser look-ahead or type information in certain situations (see the end of this e-mail for an example). This leaves us…

How does using [] for generics decrease user clarity? They're both just grouping characters. If the argument is that [] is easy to confuse with indexing, then by the same token is also easy to confuse with comparison operators. One could also argue that [] is the better choice precisely because it is similar to indexing a map - a generic type can be seen as a map of types to other types.

It certainly does for me. It ties into this quote:

> Why not use the syntax F like C++ and Java?

A great number of us are used to seeing rather than [] for generics.

It would seem limitations in Go's parser outrank a popular norm.

Re: Go 1.18

#440
post #256

Earlier quoted context omitted.

I would agree with you in the general case, but I yet to hear any sort of sane explanation for why it is the way - and it is not like a typical tradeoff where something arguably worse would have been chosen otherwise, it is just a small semantic change to a keyword. But its effect is huge, e.g. the prototypical usage of the keyword would be to unlock mutexes, but it is simply a huge footgun, see: https://news.ycombin…

It enables one to conditionally set up cleanup within the function. If it was block scoped, you couldn't do something like `if shouldDoSideEffect { defer something() }` If it was scope-based, there would be just as many people complaining that it isn't function based.

You could just do `defer if shouldDoSideEffect { something() }`
Post reply on HN