1. 33
  1.  

  2. 24

    Compared to the mess I’ve seen with reflect, these are really crimes on the level of jaywalking.

    1. 3

      Huzzah, crimes!

      Sometimes computations can be treated as values, but this is very rare. It’s even more rare to take a partially completed computation and use it as a value.

      Pshaw. :-P

      1. 2

        Some years ago I worked on a fuel wetstock management system that had a lot of partially completed computations passed around.

      2. 2

        The YouTube link at the end is not working, because the video is private. Given that it’s public on Twitch, I assume it’s not intended?

        And yeah, I am pretty sure we will use a lot of crimes in Go using generics. Language features sadly tend to be abused in one way or another. The good thing is that there is quite a culture on using stdlib in Go, which helps a lot with protecting oneself from things ending up in your code. At least as long as the current core team/creators of Go keep an eye on it.

        1. 10

          It is intended. I have to have exclusivity on Twitch for a period of time due to being an affiliate, so the YouTube video is scheduled to go public after that exclusivity ends.

        2. 2

          Gonads is a real word that has nothing to do with Go nor monads, and I can’t decide if I think this was intentional or not.

          1. 3

            Mara: What is that package name?

            Cadey: It’s a reference to Haskell’s monads, but adapted to Go as a pun.

            Pretty sure it’s intentional 😉

            1. 1

              possibly a reference to a talk by someone who didn’t know what they were talking about

          2. 1

            If I remember correctly, when Go’s original design goal was to not have any generics. Maybe it was something to do with the way C++ did templates and leaving a bad taste in everyone’s mouth? I don’t remember but I’ve used generics and have never been in a situation where doing without generics wasn’t preferable or at the very least not worse. I seem to only hear generics being misused or absolutely needing generics.

            Maybe we should have generics in case they’re absolutely needed knowing that 99% of use cases you don’t need them and you’re just being clever? Or am I being daft?

            1. 1

              and you’re just being clever

              Yes, but I find not trying to be clever one of the hardest things to do in programming. It’s so very tempting.

              1. 1

                How would you, say, make a decent multi-thread-safe hash map without generics? Go’s sync.Map has serious performance problems because the only data structures which can be generic are the built-in implementations of maps, channels and arrays. Everything else has to use runtime polymorphism with indirection through interface{}.

              2. 1

                I made something like Thunk with sync.Once: syncx.Once. It’s concurrency safe, which has pros and cons.

                1. 1

                  “Crimes with X” is my new favorite phrase for language perversity

                  1. 1

                    Does Go not have some kind of sum type/tagged union thing?

                    1. 3

                      No, you can technically do an untagged union with constraint types but it’s not intuitive

                      1. 1

                        If not ideal, could you make your Optional[T] (or whatever the syntax is :) ) do that but have a sane interface? then support Optional[SomeValueType]? Or is the allocation sufficiently cheap in Go that it isn’t a concern? (I recall Sun/Oracle making such claims long ago, but the “FlyWheel Pattern” (Yay useless for retaining 20 year knowledge from university software engineering courses!) existed to deal with that not actually being true.

                        My experience has generally been that those claims are simply never actually true. When I was working on JSC’s GC, even if we had numbers in a separate heap that knew exactly what it was storing, with fixed size pointer increment (as in generated code including the increment as an immediate) for allocation, we vastly got superior runtime on 32bit x86 by switching to 64-bit tagged values (and so double register on the hilariously constrained IA32).

                      2. 1

                        The current version of Go allows you to have type parameter constraints that are effectively a sum type, but you can’t have a variable that has a sum type.

                        1. 1

                          Sorry, what I meant is could you do something like this:

                          type Optional[T any] struct {
                             theRealValue magic_sumtype[T]
                          }
                          

                          with whatever type goop is needed to create magic_sumtype work?

                          Then have

                          func foo(stack *Stack[T]) {
                            someOptionalValue = stack.pop()
                          }
                          

                          or something, and have that be valid despite being a local?

                          1. 1

                            I don’t understand what you mean by local.

                            1. 1

                              Sorrry, a variable.

                              1. 1

                                I still don’t understand the question or follow the example. Is the question whether a variable can have a type parameter? The answer to that is no.

                                1. 1

                                  Ok inferred type parameter then, whatever.

                                  What I’m trying to understand is whether you could get make a value typed Optional[T] struct and use it with any type, including structs and other non-object types

                                  1. 1

                                    Yes, that’s the whole point of generics.

                                    Go doesn’t distinguish between “value types” and “reference types” though. It has pointers, and then it does program analysis to decide whether a value lives short enough to be stored on the stack or must be stored on the heap. (You can’t directly decide whether to use the stack or heap.)

                                    If you want to reduce fragmentation with an Optional, you can store it as type Optional[T any] struct { value T; valid bool}. That will stack allocate if possible and can be put into a slice.

                        2. 1

                          The usual approach for “sum-types” in an object oriented language is to use something like Kotlin’s sealed classes. Similarly in Go, you could use an interface with a marker method, and specific structs for each case (this might be what @cadey means in her comment).

                          The downside is that it’s a lot harder to tell if you’ve matched on a type exhaustively, or not. Not to mention the risk of getting funny looks from your co-workers.