Live data from Hacker News

Go 1.27 Interactive Tour

victoriametrics.com

171–180 of 219 posts

Re: Go 1.27 Interactive Tour

#172
post #89

Earlier quoted context omitted.

It's hard to avoid, because (naming aside) the cognitive load is caused by higher order functions, which are hard avoid without causing massive code duplication. I understand the desire to keep things concrete and avoid high level abstractions, but it's a decision not to automate stuff that can easily be automated. It runs counter to the basic instincts and purpose of our field/industry. That's why it never sticks.

Honestly, I’ve written some applications that, on paper, should be the perfect candidate for generics. And yet I can still count on one hand the number of times generics have saved me from massive code duplication. Most of the time generics might be useful, I’ve ended up needing reflection too anyway. And at that point, I’m really no better off for generics.

Generics are supremely useful for containers. They are kind of one trick ponies in that sense in application code. Similar to reflection, I’d say, which is utilized for serialization 99% of the time.

The thing is that one use case is so essential, so foundational, that we really can’t just skip it. You need generic containers, for ergonomics and performance. I mean, compare C qsort to C++ std::sort.

The languages that “get around” generics, like PHP, include god containers in the runtime. The language I’m designing is also that way, I’d like to avoid generics preferably forever.

But there’s a tradeoff there. God containers are very flexible, and we’ve seen the ramifications of untyped PHP arrays.

Re: Go 1.27 Interactive Tour

#173
post #162

"The best way to teach something new is to compare it to something the audience already understands." Could someone take the example, reduce it to a non-generic version for two types I DO understand, then show that with the new feature I can collapse them into the Box/Map example in the doc? I have 10+ years of Go experience and I can't make heads or tails of "(b Box[T]) Map[U any](f func(T) U) Box[U]"

If you instantiate it with concrete types, does "(b IntBox) Map(f func(int) string) StringBox" make more sense? You have a collection (in this case Box) containing values of type T, a function that maps values of type T to type U, and if you apply that function to all elements in that collection you get a collection of type U.

Only they are not using a collection and therefore "Map" was a confusing choice for the method name (maybe "To" would have been a better name?).

Re: Go 1.27 Interactive Tour

#174
post #173
post #162

Earlier quoted context omitted.

If you instantiate it with concrete types, does "(b IntBox) Map(f func(int) string) StringBox" make more sense? You have a collection (in this case Box) containing values of type T, a function that maps values of type T to type U, and if you apply that function to all elements in that collection you get a collection of type U.

Only they are not using a collection and therefore "Map" was a confusing choice for the method name (maybe "To" would have been a better name?).

Is that really the confusing part? If you had a general collection interface, say Mapper, a Box (i.e. a singleton set) could implement it just as well as a List or a Tree.

Re: Go 1.27 Interactive Tour

#175
post #173
post #162

Earlier quoted context omitted.

If you instantiate it with concrete types, does "(b IntBox) Map(f func(int) string) StringBox" make more sense? You have a collection (in this case Box) containing values of type T, a function that maps values of type T to type U, and if you apply that function to all elements in that collection you get a collection of type U.

Only they are not using a collection and therefore "Map" was a confusing choice for the method name (maybe "To" would have been a better name?).

A one item collection is admittedly a lame one, but it is a collection. Pointers are collections of zero or one items in a sense.

Now, the verb "map" is the traditional name for this operator, but I agree it sounds confusing when the noun "map" is also a collection type. C# and SQL call this Select, if that helps.

Re: Go 1.27 Interactive Tour

#176
post #174
post #173

Earlier quoted context omitted.

Only they are not using a collection and therefore "Map" was a confusing choice for the method name (maybe "To" would have been a better name?).

Is that really the confusing part? If you had a general collection interface, say Mapper, a Box (i.e. a singleton set) could implement it just as well as a List or a Tree.

I realize that mathematically speaking a singleton set is still a set, but as a programmer who is used to map operations in other mainstream languages, I was expecting some kind of loop in the implementation. It took a few page faults in my brain to realize what's going on.

Re: Go 1.27 Interactive Tour

#177

Earlier quoted context omitted.

Yeah a few years ago there was a lot of buzz around it, but ultimately when presenting and polling all the options to the community, the general consensus was that existing error handling was actually fine. The other options added complexity and were harder to read.

[flagged]

Rust's solution (the ? operator) is actually applied to the Result type (and, IIRC, Option and ControlFlow). Go does not have a Result type. This makes a 1:1 port of Rust's solution impossible.

Moreover, the "obvious" solution, i.e. treating (T,error) returns the same as Result, does not actually work. The problem is that (T,error) behaves like a product type while Result is a sum type and yes, some Go code does (ab)use this. In particular, the io.Reader.Read method in the standard library allows implementers to return (n>0,io.EOF), which has no equivalent Result representation. Many people consider this allowance to be a mistake, but it's too late to change it.

Re: Go 1.27 Interactive Tour

#178
post #176
post #174

Earlier quoted context omitted.

Is that really the confusing part? If you had a general collection interface, say Mapper, a Box (i.e. a singleton set) could implement it just as well as a List or a Tree.

I realize that mathematically speaking a singleton set is still a set, but as a programmer who is used to map operations in other mainstream languages, I was expecting some kind of loop in the implementation. It took a few page faults in my brain to realize what's going on.

Your understanding is quite incomplete. Wait till you think about the mapping operation for functions. Then there’s no loop, just function composition.

Re: Go 1.27 Interactive Tour

#180

Earlier quoted context omitted.

I understand that this is true for a lot of application code. It's not true for library authors though, and every language needs libraries.

I’ve written a lot of libraries too. The problem is generics only solve a very small part of the equation: compile time checks for composite types. But to use composite types in anything non-trivial in Go, you then need reflection. Which is slow. And if you then need reflection, you’re already passing interface types anyway plus you’re back to having to handle type-handling errors in the runtime. So if you’re writing…

Yes it is precisely Go’s shortcomings that would require typical use of generics to also require reflection most of the time. You would want Rust traits (or Haskell type classes) or C++ style type traits and then the need for reflection is much reduced. So Go has painted itself into a corner where generics feel bolted on and less useful than generics in other languages. It’s still Go’s fault and people rightfully argue that they should prefer a different language.

The Go language itself is never its strength but it has a good runtime, wonderful standard library and tooling. People never picked Go for being an amazing language, but rather for these other things.

Post reply on HN