Live data from Hacker News

Go 1.27 Interactive Tour

victoriametrics.com

181–190 of 219 posts

Re: Go 1.27 Interactive Tour

#181

"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]"

This is the kind of shit why they probably didn't want generics in the language. This is like building a very crude general-ish DSL inside the language. Because the tools are intentionally limited (as to limit the scope of the feature), the result looks ugly. Also, like with C++ templates, people find exploits to do what the designers didn't want them to, with even more elaborate workarounds. I liked Go before generi…

I think you're right and it is sad to see. I think had they stuck to their guns, the language might not feel like it has lost the point.

Re: Go 1.27 Interactive Tour

#182

"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]"

I think part of the issue is that they didn’t explain what is gained by adding generics on methods. You’re right that a few examples here are useful.

Without generics:

‘’’

type Stream[T any] struct{ ... }

func (s Stream[T]) MapInt(f func(T) int) Stream[int] { ... }

func (s Stream[T]) MapString(f func(T) string) Stream[string] { ... }

‘’’

Then later you need to map floats:

‘’’

func (s Stream[T]) MapFloat64(f func(T) float64) Stream[float64] { ... }

‘’’

Then later someone outside the package wants to map a custom type. Too bad! They’ll need to make some custom wrapper that doesn’t follow the pattern.

With the genetics approach the semantics are defined once and usable in all scenarios. You don’t need to keep adding methods; instead the caller can provide the mapping function. Common mapping functions could be pre defined for convenience.

Re: Go 1.27 Interactive Tour

#183
post #118

This: "(b Box[T]) Map[U any](f func(T) U) Box[U]" is the type of cognitive weight I was happy that Go avoided.

We often forget that our profession (computer programming) belongs to STEM. Some (like Go 1.0 :)) wish to think it is Arts & Humanities. The sooner we realize that yes, it is OK and actually expected to bear a cognitive weight of "(b Box[T]) Map[U any](f func(T) U) Box[U]" the sooner we get back to reality... :)

Programming language evolution has always been the pursuit of abstractions that enable expressiveness and simplicity.

Your comment boils down to "I'm smart", which in the end, isn't terribly smart.

Having simplicity and expressiveness as a goal, and a general direction of achieving things through lazy means is at the heart of mathematics and engineering.

Celebrate laziness and a want for simplicity. True simplicity is hard, but worth going after even where it threatens the notion that you're the smartest person in the room.

Re: Go 1.27 Interactive Tour

#184

"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]"

This is the kind of shit why they probably didn't want generics in the language. This is like building a very crude general-ish DSL inside the language. Because the tools are intentionally limited (as to limit the scope of the feature), the result looks ugly. Also, like with C++ templates, people find exploits to do what the designers didn't want them to, with even more elaborate workarounds. I liked Go before generi…

As a bit of a counterpoint, I help maintain SDKs for Hatchet in multiple languages (largely Python and TS, but also contribute to Go a bit too) that benefit heavily from generics. It's especially useful for things where users of the SDK provide e.g. return types from functions they register, and we want those to be strongly-typed elsewhere in the codebase. A simple Python example is:

  @hatchet.task()
  async def my_task(...) -> SomeOutputType:
    return SomeOutputType(...)

  ## imagine this is an API handler:
  @api_handler("/some/path")
  async def handle() -> ...:
    result = await my_task.run(...)

    # we now know `result` is of type `SomeOutputType` without any sort of type assertion, etc.
Admittedly, I'm not a Go expert, nor am I a programming languages expert. But I do feel that this type of behavior is really only possible (with nice ergonomics) with generics, and it's always been upsetting to me that somehow Python's type system feels more complete than Go's in this arena, or at least it has until more recently.

Maybe this falls into the 1% of cases, but I'd suspect this sort of thing is more common than that.

Edit: I should have mentioned - in the Python example above, `@hatchet.task` is generic with the output type of the task it wraps.

Re: Go 1.27 Interactive Tour

#185

Earlier quoted context omitted.

Tried reading your comment but ran into a lack of usable information.

If you try a new thing and run into 1 (or maybe 2 errors), maybe it's worth the time to report them. If you run into a few errors, it's into "this isn't ready" or "they didn't try hard enough" territory, and it's not worth reporting the problems.

It's also not worth posting "I tried didn't work" because nobody knows what you tried. There is zero information in it, and it's a waste of bits that just pollutes the discussion.

Re: Go 1.27 Interactive Tour

#186

Earlier quoted context omitted.

This is the kind of shit why they probably didn't want generics in the language. This is like building a very crude general-ish DSL inside the language. Because the tools are intentionally limited (as to limit the scope of the feature), the result looks ugly. Also, like with C++ templates, people find exploits to do what the designers didn't want them to, with even more elaborate workarounds. I liked Go before generi…

As a bit of a counterpoint, I help maintain SDKs for Hatchet in multiple languages (largely Python and TS, but also contribute to Go a bit too) that benefit heavily from generics. It's especially useful for things where users of the SDK provide e.g. return types from functions they register, and we want those to be strongly-typed elsewhere in the codebase. A simple Python example is: @hatchet.task() async def my_task…

And I'm not a python expert, so I might be wrong here, but:

My understanding is that this decorator generates some class in the background that wraps the function into some remotely executable container thing, and handles the networking?

Since python is a dynamic language, and go is not, this would be impossible without codegen, generics or not, but go does have codegen facilities.

And the more immediate implication, that many OOP languages do (and seems to be going on in here) is that they handle asynchrony via some generic Awaitable[T] pattern.

Go does not do this, generally the way you handle asynchrony and abstract typed results is by using channels. You don't await on 'smart' objects, you read from channels (which are 'generic' in a way, but they are the few exceptions where go used to allow this behavior).

Re: Go 1.27 Interactive Tour

#187

Am I the only one who’s absolutely shocked that Go finally is embracing generics? Does anyone have a bit of an inside view into what changed in the perspectives of the language maintainers? I’m not buying the “it took us 20 years to understand how to do it correctly” argument, as this is something you explicitly take into consideration when designing the language or not. And it was specifically not a part of language…

> Am I the only one who’s absolutely shocked that Go finally is embracing generics?

Yes. Everyone else knows that they were always expected to be included at some point, as told when Go was first announced to the world: https://www.youtube.com/watch?v=rKnDgT73v8s&t=3267s

> So what changed?

Philip Wadler, of Haskell fame, decided to help? This was well publicized on HN at the time.

> I’m not buying the “it took us 20 years to understand how to do it correctly” argument

If I recall correctly, Pike suggested that they never would have been able to come to that understanding without the outside help. I can understand why you are surprised that it took 20 years for someone with the right expertise to show up. You can get the sense in the above announcement that even the Go team thought that open sourcing the project would attract the right talent far, far earlier. But, now that we have hindsight, we can see that all the experts on HN who could have been the missing positive contributor were too busy complaining that Go didn't have generics. There wasn't enough time left for them to lend a hand. There are only so many hours in the day.

Re: Go 1.27 Interactive Tour

#188
post #155

Earlier quoted context omitted.

You just do dictionary passing.

Like this, you mean? https://haskellforall.com/2012/05/scrap-your-type-classes Fine in principle, but AFAIK it never really caught on because the ergonomics suck. Interfaces/traits/type classes do seem to be a popular feature across languages, for what it's worth.

right but type classes are basically vtables aka dictionary passing but the compiler figures out which dictionary to summon for you

but the key is they build seamlessly on top of real parametric polymorphism. you still get a real "forall a." in your proposition language.

Go fucked up early on with their core language design due to an inability to learn from the 1970s so now it's terminally dookie sadly

Re: Go 1.27 Interactive Tour

#189

Earlier quoted context omitted.

As a bit of a counterpoint, I help maintain SDKs for Hatchet in multiple languages (largely Python and TS, but also contribute to Go a bit too) that benefit heavily from generics. It's especially useful for things where users of the SDK provide e.g. return types from functions they register, and we want those to be strongly-typed elsewhere in the codebase. A simple Python example is: @hatchet.task() async def my_task…

And I'm not a python expert, so I might be wrong here, but: My understanding is that this decorator generates some class in the background that wraps the function into some remotely executable container thing, and handles the networking? Since python is a dynamic language, and go is not, this would be impossible without codegen, generics or not, but go does have codegen facilities. And the more immediate implication,…

Ah yep! I should’ve given a Go example. In Python we use decorators because it’s what’s in fashion, but in Go and TypeScript you just create a `NewTask()` e.g. where you pass a function (as well as other args), and it returns something with e.g. a `Result` method. And that result method, which is generic, is the thing that’s really nice to have typed.

Agreed codegen works fine here too by the way, but it feels kind of clunky to me (it’s something I don’t love about Go, although I know it’s also an important part of the ecosystem and is popular).

Re: Go 1.27 Interactive Tour

#190
post #59

> interfaces still can’t declare type-parameterized methods What would an implementation look like? Wouldn't it be quite different from the existing one because it has to rely heavily on indirection because (limited) monomorphimization is not possible?

Probably won't/cannot be ımplemented. C++ and Rust disallow the analogues of this (templated virtual methods/dyn with a trait containing methods taking type parameters) as well.

[deleted]
Post reply on HN