[HN Gopher] Generics enabled by default in Go tip
       ___________________________________________________________________
        
       Generics enabled by default in Go tip
        
       Author : dcu
       Score  : 242 points
       Date   : 2021-08-21 02:52 UTC (20 hours ago)
        
 (HTM) web link (go-review.googlesource.com)
 (TXT) w3m dump (go-review.googlesource.com)
        
       | tedunangst wrote:
       | Every HN thread about go: go is useless because it lacks
       | generics.
       | 
       | Go adds generics.
       | 
       | HN thread: I don't want this.
       | 
       | Good case study about the people drawn to comment on a topic.
        
         | zenlot wrote:
         | Been reading through comments and wanted to say exactly this :)
        
         | silisili wrote:
         | Or good case study of squeaky wheels. I never wanted generics.
         | I never thought to spam the development lists about how much I
         | liked how things were going.
        
           | bigdubs wrote:
           | a couple high profile projects (k8s) needed generics, there
           | are limited use cases outlined in the planning docs that
           | detail the holes in the language they're filling, it wasn't
           | just squeaky wheels.
        
             | silisili wrote:
             | Shame how k8s was a failure without generics. Think what
             | could have been.
        
               | pjmlp wrote:
               | UNIX was re-written in a clunky unsafe systems
               | programming language, by being free beer due to legal
               | impositions on research work, its adoption settled the
               | future of this language across the industry.
               | 
               | Yet even C supports lightweight generics, so they must be
               | worth something.
        
               | Zababa wrote:
               | The thing is, Google is paying most of the development
               | costs for Go and Google controls Go too. It makes sense
               | to adapt the language to their needs. They already do
               | stuff like creating new network protocols because it will
               | reduce their costs.
        
               | loopz wrote:
               | Google have alternatives to k8s already. So it's more
               | about making a market.
        
               | Zababa wrote:
               | I've heard multiple times that Google Cloud has the best
               | support for k8s, and that people moved to it because of
               | that. Is that what you meant by making a market?
        
               | loopz wrote:
               | That and open sourcing it.
        
             | dilyevsky wrote:
             | Maybe you can get rid of some runtime.Object casting here
             | and there (I suspect at the cost of major compilation time
             | penalty) but pretty sure the codegen is here to stay
        
         | smcl wrote:
         | You're making it sound like these are the same group of people
         | and they're just really fickle, whiny and impossible to please.
         | But my memory of these older go/generics threads were that
         | commenters were split between "I love go, I wish it had
         | generics" and "I love go, I don't think it needs generics". The
         | former have no need to comment anymore, the latter will still
         | want to express their feelings.
        
         | anothernewdude wrote:
         | The people who cared about Go not having generics (myself
         | included) moved on. The time for a well designed language with
         | Generics was five years ago.
         | 
         | The only people who care about Go now are the ones who
         | convinced themselves that casting from empty interfaces was
         | okay.
        
           | erik_seaberg wrote:
           | My employer has not moved on and it's steadily encroaching
           | more even on strong Scala/Java teams, so I'm glad to see the
           | worst impediments start getting fixed.
        
           | hyperman1 wrote:
           | Yes and no. I dropped go after a short but tumultous
           | love/hate relation, but decided to take a fresh look if
           | generics had a decent answer. There's a lot to like about go.
           | So I'll look back soon.
        
           | zimpenfish wrote:
           | Dunno about the rest of the world but London definitely seems
           | to be embracing Go - many more jobs going now than even a
           | year ago.
        
         | baby wrote:
         | It's almost like HN is not a single person
        
         | masto wrote:
         | I don't know, at this point my guess is that most people just
         | don't care, so those that can be bothered to comment are a bit
         | fringe.
         | 
         | When Go first came out, it seemed interesting, but when I
         | checked it out it felt more like throwing out the baby with the
         | bathwater than introducing anything of value. Not every idea
         | since 1972 is bad. So I tried to force myself to use it for a
         | project or two, got frustrated by exactly the things people
         | were complaining about, and never looked at it again.
         | 
         | I haven't seen any meaningful adoption, so my hypothesis is
         | that by not having the features mainstream users want, Go
         | missed its window of opportunity and the world moved on. It's
         | neat that they're adding them now, but.. well.. let's just say
         | that I was an absolute die-hard Perl fan for a long time so I'm
         | familiar with this pattern.
        
           | mseepgood wrote:
           | > I haven't seen any meaningful adoption
           | 
           | You must live in a different world. Go has been an immense
           | success since its inception. Cloud, DevOps and SRE are
           | nowadays unthinkable without it.
        
             | pjmlp wrote:
             | I must be doing something wrong with Java, .NET and
             | Powershell.
        
         | randomdata wrote:
         | From what I have seen over the years, the "I don't want
         | generics" crowd showed up just as often as the "Go is useless
         | without generics" crowd. This time, though, only one of those
         | groups can reasonably continue to comment.
        
           | [deleted]
        
         | dmix wrote:
         | This is why you have to be a tough leader when you're the
         | designer of anything. But especially languages which naturally
         | draw an endless barrage of comparisons and tribal opinions.
         | 
         | You see this a lot in web design, everyone thinks they're an
         | expert at what makes a good website - simply because they are a
         | consumer of them. Even if they only have minimal experience
         | building one IRL.
        
         | SideburnsOfDoom wrote:
         | > Go adds generics. HN thread: I don't want this
         | 
         | If generics are a good idea for a language, then it's better to
         | add them in version 0.01 of the language and build up from
         | there with generics as an intrinsic part of the language and
         | standard libraries.
         | 
         | No, I don't want _tacked on_ generics.
         | 
         | Generics are not in 2021 a "bleeding edge" feature, that
         | _might_ be useful later. They are established and proven in
         | ways that they were not when Java v1 or C# v1 shipped - both
         | added generics in later releases, with associated compromises.
         | Now, you can and should choose upfront if your language needs
         | them, or to choose a different route. There's no need to repeat
         | that history.
         | 
         | YMMV, people have different preferences in programming
         | languages, I have always preferred strongly typed languages.
         | Generics suit me, but pick your lane.
         | 
         | And if you're at version 0.01 of a language, while you're at
         | it, look at being immutable by default, not null by default.
         | Those things can be opt-in for when you need them.
        
           | iainmerrick wrote:
           | _No, I don 't want _tacked on_ generics._
           | 
           | What languages in your opinion have good, non-tacked-on
           | generics? Are they generally better than other languages?
           | 
           | Here are some pretty successful languages that gained
           | generics after maturity: C++, Java, C#, TypeScript (based on
           | JavaScript), Objective-C, even Python.
        
             | spion wrote:
             | The libraries are better because they're designed with
             | generics in mind.
             | 
             | Most C# libraries in use today were built after generics
             | were added, and there never was a large ecosystem already
             | developed at the time
             | 
             | Java has had lots of libraries thrown away due to initial
             | lack of generics and a lot of painful migration e.g. https:
             | //docs.oracle.com/javase/tutorial/extra/generics/conve...
             | 
             | A good parallel would be async-await in JS and nodejs. The
             | entire core library and a huge percentage of the ecosystem
             | ended up being really awkward to use after the introduction
             | of async await. The whole ecosystem is now one big giant
             | mess.
        
             | pjmlp wrote:
             | Ada, ML, Modula-3 and CLU got generics since day one.
             | 
             | In fact, so much research and Go generics are mostly
             | similar to CLU.
        
             | josefx wrote:
             | > C++
             | 
             | The parsing rules for templates alone probably make a
             | decent door stopper. They can also trivially kill compile
             | times. The bloat from page long symbol names also isn't
             | something to ignore, just
             | std::map<std::string,std::string>::find() results in a
             | decent chunk once the compiler is done expanding it.
             | 
             | > Java
             | 
             | That is a can of worms, haven't professionally worked with
             | Java in some time, but from memory:
             | 
             | * Compile time only, reflection or serialization heavy code
             | will get raw Object types, yay type safety.
             | 
             | * They do not support primitive types, resulting in object
             | boxing and null-ability issues by default as well as third
             | party copy paste libraries that provide collections
             | specialized for primitives.
             | 
             | * You cannot create an object or array using a generic type
             | as that is unknown at runtime, as result some methods
             | require a concrete array as argument just so they can
             | create their own array with the correct runtime type.
             | 
             | * It is fully backwards compatible, so nothing will tell
             | you if you have a compiled library that uses raw types
             | somewhere in your application dumping Integers into a List
             | that should only contain Strings.
             | 
             | * Calling code has to verify object types using runtime
             | casts, you may not want to pay the cost of that.
             | 
             | I could probably go on ...
             | 
             | > Python
             | 
             | Aren't those just hints that the interpreter completely
             | ignores? I have a python 3 toy project that could have
             | benefited from better type checking - the contents of its
             | sqlite database are a mess.
        
               | vips7L wrote:
               | Fwiw generics in Java should have less holes once they
               | start releasing things from Valhalla.
        
             | SideburnsOfDoom wrote:
             | > What languages in your opinion have good, non-tacked-on
             | generics?
             | 
             | It's cliche, but it's clear that generics like Result (
             | https://doc.rust-lang.org/std/result/ ) and Option (
             | https://doc.rust-lang.org/std/option/ ) are fundamental to
             | Rust's design from the start.
             | 
             | > some pretty successful languages that gained generics
             | after maturity
             | 
             | I'm very familiar with C#, of course it is a "pretty
             | successful language", no kidding. I did not say otherwise,
             | I said that there are "compromises" associated with adding
             | generics in V2.
             | 
             | And there are: e.g. starting with collection types,
             | interfaces and base types in pairs, such as List<T> and
             | List, IList<T> and IList, IEnumerable<T> and IEnumerable,
             | etc ad nauseam. Then Delegates that precede Func<T> and
             | Action<T>.
             | 
             | I suggest that you reread my comment above; the point is
             | not just that adding generics later causes complication
             | (historic record is clear that it does).
             | 
             | The point is that generics were _not_ proven in mainstream
             | OO programming when c# 1.0 was released in 2002, but this
             | has changed; now they are. Designs done in the last few
             | years can avoid this complication: Ether your language
             | wants them from the start, or it intends other ways to deal
             | with the same kinds of problems.
        
             | xigoi wrote:
             | > What languages in your opinion have good, non-tacked-on
             | generics?
             | 
             | ML and its derivatives, Haskell, Rust, Nim.
        
           | R0b0t1 wrote:
           | These don't seem tacked on. They spent so long on them
           | specifically so they don't seem tacked on.
           | 
           | The issue with Go is if you're not shuffling around binary
           | data it has horrible developer ergonomics. Network data is
           | usually untyped, but if you start needing to care about what
           | is in that data and need typed datastructures built around it
           | you stop having fun quick. Same issue with C, really.
        
           | masklinn wrote:
           | > Generics are not in 2021 a "bleeding edge" feature, that
           | _might_ be useful later. They are established and proven in
           | ways that they were not when Java v1 or C# v1 shipped - both
           | added generics in later releases, with associated
           | compromises.
           | 
           | Generics were hardly bleeding edge by 2002. Doesn't mean the
           | average developer understood the point, but that's hardly a
           | benchmark, and really most people have a hard time
           | understanding what they have no experience with.
           | 
           | And work on .net generics had been going on since 1998, and
           | by the release of 1.0, generics were going to land in 2.0. It
           | simply wasn't done at that point: "Design and Implementation
           | of Generics for the .NET Common Language Runtime" dates back
           | to early 2001, but by late 2001 the spec was still incomplete
           | and debated (https://docs.microsoft.com/en-
           | gb/archive/blogs/dsyme/some-hi... used to have a link but
           | it's dead).
        
             | SideburnsOfDoom wrote:
             | > Generics were hardly bleeding edge by 2002.
             | 
             | yes and no. It's clear from the history at the time that
             | they were not a proven, obvious win.
             | 
             | > Generics for .NET and C# in their current form almost
             | didn't happen
             | 
             | > being told by product team members that "generics is for
             | academics only"
             | 
             | https://docs.microsoft.com/en-gb/archive/blogs/dsyme/netc-
             | ge...
             | 
             | My argument is that this particular question has, since
             | then, been settled in favour of generics, outside of
             | academia, and in mainstream languages such as c#. Generics
             | are now "established and proven" in ways that they were not
             | then.
             | 
             | Hindsight:
             | https://twitter.com/matthewwarren/status/920667986108846080
             | 
             | C# is IMHO mainstream, deliberately so. Features in it
             | typically come from other languages. It is a "populariser"
             | of promising programming language ideas for mainstream
             | productivity, not a testbed.
             | 
             | > Doesn't mean the average developer understood the point
             | 
             | at the time as a junior dev, I got the point inside a
             | minute: I was already in the habit of when declaring
             | Customer class adding a strongly typed CustomerList class,
             | for their address, an Addess class, followed by the
             | AddressList, and Orders needs OrderList and OrderItemList.
             | Reducing this repetitive "plug in the type" code to
             | List<Customer> etc was such a clear win.
        
               | masklinn wrote:
               | > I was already in the habit of when declaring Customer
               | class adding a strongly CustomerList class, for their
               | address, an Addess class, followed by the AddressList,
               | and Orders needs OrderList and OrderItemList. Reducing
               | this repetitive "plug in the type" code to List<Customer>
               | etc was such a clear win.
               | 
               | TBF a common rejoinder back then was that this specific
               | pattern made the opportunity cost of domain-specific
               | operations very low, so you could better those collection
               | interfaces to the specific needs.
               | 
               | Of course 95% of the time they extended the corresponding
               | class or implemented the interface so that wasn't
               | actually true.
        
               | SideburnsOfDoom wrote:
               | > this specific pattern made the opportunity cost of
               | domain-specific operations very low,
               | 
               | Yes, I did miss the "added value" operations declared on
               | that list class, e.g. AddressList typically contained a
               | "GetCustomerPrimaryAddress", etc.
               | 
               | But there were ways to bring that back, by subclassing or
               | (later) extension method on that list. Indeed, 95% of the
               | code was tedious forwarding to the non-generic non-
               | typesafe "list of objects".
               | 
               | Around the same time the dominant pattern of saving or
               | loading data to a data store moved from "active record"
               | where these methods were common, to "repository and DTO"
               | where they were not. Might be co-incidence.
        
         | 1penny42cents wrote:
         | Isn't that the response you should expect on any topic where
         | the population's preference is split across a decision line?
         | 
         | When go didn't have generics, those in favor commented. Now
         | that it will, those against are commenting.
         | 
         | It sounds funny at face value but I don't see the insight.
        
         | dgellow wrote:
         | That's because "HN threads" represents a lot of different
         | people with different needs and opinions. It's not a monolithic
         | block at all, and people are more likely to react to complain.
        
           | Zancarius wrote:
           | > people are more likely to react to complain.
           | 
           | You hit the nail on the head. This is broadly true across
           | virtually everything--at least in most of Western culture (as
           | this is the only one I'm most familiar with).
           | 
           | Anger seems to provoke a more actionable response whereas
           | satisfaction does not (generally speaking). Is someone more
           | apt to call a business over lousy service or great service?
           | Why is it that giving a compliment to someone in customer
           | service sometimes provokes a brief reaction of surprise? I
           | try to do my part as a positive force when I can, but I
           | usually fall short. Besides, is one happy person likely to
           | make _that_ much of a difference over the course of a day?
           | Maybe, maybe not.
           | 
           | FWIW I actually like the idea of generics in Go and have a
           | few use cases where they'd be exceptionally helpful in
           | cutting down the amount of code I have floating around in
           | some libraries. I just don't feel strongly enough about it to
           | jump into a thread to rush to its defense.
        
         | SergeAx wrote:
         | I am okay with generics as long as they are not affecting
         | compile time. I love Go for blazing fast builds and testing and
         | afraid generics will degrade it. Otherwise, generics are adding
         | some cognitive complexity to code, but I don't have to use them
         | and will just occasionaly have to figure them out in libraries.
        
       | sascha_sl wrote:
       | If you're really concerned about "clever developers", maybe you
       | ought to ask for the removal of reflect and ast, because they've
       | both been used to be way too clever about solving the same issue.
        
         | valenterry wrote:
         | Correct. People _will_ find a way to get rid of the verbosity
         | and you either give them good tools to do it or you end up with
         | a mess.
        
       | i_have_to_speak wrote:
       | It is available in Go 1.17 with a flag, use:                   go
       | run -gcflags=-G=3 foo.go
        
         | uluyol wrote:
         | The support in Go 1.17 is very incomplete. A lot of work has
         | been done in a branch (since merged) after the 1.17 freeze.
        
       | peter_l_downs wrote:
       | Super excited for this. If you haven't checked out the latest
       | proposal, here's an example of what Option/Result box types might
       | look like (obviously not ready for release, just an experiment):
       | 
       | https://go2goplay.golang.org/p/krvTH1_7lwX
        
         | tapirl wrote:
         | Each Unwrap() call needs two OK() calls? Letting Unwrap return
         | OK would be better?
         | 
         | BTW, the readability is really not good as Go 1.
        
           | SPBS wrote:
           | As it rightfully should. God forbid people start returning
           | Result[T] types instead of (T, error) and splintering the
           | ecosystem.
           | 
           | Option types are pointless if you don't have exhaustive
           | pattern matching to ensure correctness.
        
             | 4ad wrote:
             | Go's type system is actually expressive enough to ensure
             | exhaustiveness, although it's non-obvious and syntactically
             | heavy and impractical. I am working on a paper that will
             | explore this.
        
           | masklinn wrote:
           | > Each Unwrap() call needs two OK() calls? Letting Unwrap
           | return OK would be better?
           | 
           | That would rather miss the point as you'd be converting the
           | type-safe result to an unsafe version?
           | 
           | Go doesn't have pattern matching or any "structural"
           | construct which would allow performing this in a single step,
           | so the alternative would be to use HoFs and while Go has them
           | they're quite verbose e.g.                   func (o
           | Option[T]) Then(then func(T)) {          if o.OK() {
           | then(*o.value)          }         }         a.Then(func (v
           | int) { fmt.Printf("\tvalue = %d\n", v) })
           | 
           | which is... less than great.
           | 
           | An safe other option would be a method mapping to a slice of
           | 0..1 element and you'd use a `for range` as an `if` but that
           | seems way to _clever_ , similar to Scala's comprehensions
           | over everything which I rather dislike.
           | 
           | Also sadly the current proposal has no facilities for
           | _methods_ generic in their arguments independently from the
           | subject, so no `Map` method.
        
         | continuational wrote:
         | This seems somewhat strange to me (and I don't just mean hard
         | on the eyes):                   func (o Option[T]) Unwrap() T
         | 
         | How does Go know that T is a type parameter here, and not a
         | concrete type named T?
        
           | [deleted]
        
           | 4ad wrote:
           | Because it can only be a type parameter. There is no
           | specialization. (TBH I think that's a mistake because if
           | prevents a solution to the Expression Problem.)
        
             | masklinn wrote:
             | I don't think that's an issue, specialisation is a real
             | edge case (e.g. Rust still doesn't have userland
             | specialisation despite having always had generics) and it's
             | easy to make mistakes with it (e.g. C++'s `vector<bool>`
             | though it's probably less of an issue if you can only
             | specialise functions).
             | 
             | That methods can't be parametric is still annoying though
             | because it means utility methods can't have generic
             | parameters unrelated to the subject e.g. can't define a map
             | or fold method, because there's nowhere to put the output
             | type, it has to be a free function instead.
             | 
             | But it's not like adding the generic spec thing between the
             | subject and the method name would be a big issue so that
             | can always be added later after the MVP has been exercised
             | a bit.
             | 
             | A related "missing bit" which I'd guess they want more
             | feedback before adding would be "conditional methods" aka
             | methods which are only present if the generic types of the
             | subject have a specific property (e.g. in Rust it's common
             | for the generic container to be unbounded but for functions
             | to be bounded on specific traits).
        
               | 4ad wrote:
               | Adding it later is not impossible, but unfortunately is
               | not that easy either. Ignoring the very high bar for
               | changing Go in general, doing it this way has
               | implementation consequences that would have to be undone.
               | Also the spec change is not just a matter of adding more
               | stuff, but it requires reformalization of the existing
               | semantics because interfaces are already rank-2 types,
               | you just can't see it yet. This feature interacts with
               | interfaces.
               | 
               | It's very unfortunate thay didn't do this from the start.
               | The original paper that introduced Go generics had this
               | and used to to solve the Expression Problem.
        
           | masklinn wrote:
           | Reading the specification (https://go.googlesource.com/propos
           | al/+/refs/heads/master/des...) this flows from the type being
           | declared generic, Go will (currently at least) require the
           | receiver to be similarly generic, no specialisation, and no
           | _method constraints_ :
           | 
           | > Generic types can have methods. The receiver type of a
           | method must declare the same number of type parameters as are
           | declared in the receiver type's definition. They are declared
           | without any constraint.                   // Push adds a
           | value to the end of a vector.         func (v *Vector[T])
           | Push(x T) { *v = append(*v, x) }
           | 
           | > The type parameters listed in a method declaration need not
           | have the same names as the type parameters in the type
           | declaration. In particular, if they are not used by the
           | method, they can be _.
        
         | topspin wrote:
         | Result[T] plus a ? operator to provide concision would be a
         | huge win for Go.
        
         | nynx wrote:
         | Result isn't an enumeration of sorts?
        
           | infogulch wrote:
           | No, Go doesn't have discriminated/tagged unions or valued-
           | enumerations or whatever you want to call them, but generics
           | let you hack them in without much trouble. Personally I'd
           | take ADTs over generics any day, but it's not a dichotomy
           | maybe we'll still get them some day.
           | 
           | https://github.com/golang/go/issues/19412
        
         | ramchip wrote:
         | > Viewing and/or sharing code snippets is not available in your
         | country for legal reasons. This message might also appear if
         | your country is misdetected. If you believe this is an error,
         | please file an issue.
         | 
         | Wow, interesting. I'm in Japan.
        
           | Santosh83 wrote:
           | Shame as a species we can't even share _information_
           | (literally bits on the wire) globally, even if tangible goods
           | and movements are circumscribed by political borders.
        
           | Cloudef wrote:
           | Works for me (also japan)
        
         | takeda wrote:
         | I guess I'm understanding some of the concerns. It does make
         | the code harder to understand. I wish they would use the angle
         | brackets to match other languages.
        
       | _ph_ wrote:
       | I like Go very much, a huge role plays its simplicity. In my
       | career, I have been much more often bitten by having to deal with
       | the complexity of a language then by not being able to do things,
       | because a language feature is missing. That is, why I like Go so
       | much. It strikes a great balance between important high-level
       | features (GC, first class functions and closures) and still being
       | a simple language (like Scheme is, in a sense they are very
       | comparable in my eyes). The interface concept is great for
       | covering a lot of cases. That is, why so far, I have not missed
       | generics much and was rather reluctant to the constant wishes to
       | add them to the language.
       | 
       | On the other side, there are cases, even if they are not very
       | frequent, where generics do help a lot. Just the new slices
       | package allone almost justifies the addition of generics.
       | Furthermore, the proposal looks very much Go-like. As a
       | consequence, I am quite looking forward to try them out and used
       | responsibly[1], they can be a great addition to the Go universe.
       | 
       | 1: I think the situation is somewhat similar to Lisp macros.
       | Normally, a codebase rarely requires macros and readability is
       | better, if you avoid creating too many macros. But occasionally
       | there are situations, where using a macro tremendeously increases
       | code quality. Both implementation and readability-wise. There
       | macros should be used and it is great to have them available.
        
         | zarzavat wrote:
         | I used to really hate Go's attitude to generics and type system
         | features in general. I still do, but I appreciate that it's a
         | matter of taste, and that different people have different
         | tolerances for language complexity. People who like simplicity
         | can use Go and people who like type systems can use Rust.
        
         | papito wrote:
         | I roll my eyes when someone claims "I learned Go over the
         | weekend". It's one thing to learn basic syntax, and completely
         | another to learn the customs of your new environment so most
         | can understand what you are doing.
         | 
         | Go is one of the hardest languages to learn. First of all, some
         | concepts in it are very different from "mainstream" languages,
         | and it takes a while to get used to them.
         | 
         | Simple things that exist in almost every other ecosystem can be
         | absent in Go. Want to run setup code before your test suite?
         | You on your own, buddy. And, oh yeah, 2/3 of your code will be
         | `if err` statements, because exceptions are passe.
         | 
         | I learned it by seeking out good Go codebases, which are
         | incredibly rare. Hashi's Terraform comes to mind.
         | 
         | Infamously, the early Kubernetes code was a nightmare because
         | it lifted and shifted Java idioms _and that was at the company
         | that invented the Language_.
         | 
         | Or at Uber, where they passed on Go's native goroutines and
         | channels in favor of homegrown concurrency, for SOME reason:
         | https://eng.uber.com/go-geofence-highest-query-per-second-se...
         | 
         | All this to show that Go is not a simple language to do _well_
         | , so let's dispense with that myth.
         | 
         | It has its uses, but having done it, I would never recommend Go
         | for a greenfield project in my place of work - there are very
         | few rules that come with it, and it requires tons of
         | coordination and discipline among a team. And if you have to
         | work with 2 or 3 other people who have strong opinions on how
         | to do things in Go, watch out.
        
           | _ph_ wrote:
           | I have not claimed you can "learn Go over the weekend". Not
           | in a deeper sense where you could expect to design large
           | projects and take the right decisions.
           | 
           | But you can get a pretty good basic Go intro in a few days
           | and be pretty productive after that. It isn't that different
           | from most languages and has a rather small core. Of course,
           | it helps if you have Scheme experience, to understand all the
           | power of high order functions etc.
        
           | Someone wrote:
           | IMO, "learning the language" and "getting used to it" are
           | different things.
           | 
           | The first is a purely theoretical exercise, the second a
           | applied one that involves not only the language but also its
           | ecosystem (implementation(s), library of functions and
           | tooling)
        
             | papito wrote:
             | I am not sure if we are agreeing or not, but I feel like we
             | are. I think when people refer to "learning" a language,
             | they mean they actually know how to use it properly.
             | Learning the syntax does not count - that is just trivia
             | any one of us can do.
        
               | Someone wrote:
               | (Nitpick: I assume you mean learning both the syntax and
               | the semantics. That isn't always trivial, as some
               | languages have features one may not have seen before)
               | 
               | I think we mostly agree, too.
               | 
               | However, I distinguish between learning a programming
               | language and learning to use it. I learn many programming
               | languages without ever writing any line of code in them.
               | 
               | Once you've seen enough languages, if you combine that
               | with reading about other people's experience with working
               | with the language, that can give you a decent idea about
               | how the latter is without having to spend the effort
               | (without being as good as doing it yourself, of course.
               | Apart from "which one is the brake pedal", I think I know
               | how to drive a car, but I also know I can't drive a car)
               | 
               | That's why I posted my first comment: the poster you
               | replied to may share my opinion between "learning" and
               | "learning to use".
        
       | ledneb wrote:
       | What syntax did Go settle on, in the end?
        
         | ledneb wrote:
         | Found it, I think
         | https://go.googlesource.com/proposal/+/refs/heads/master/des...
        
       | ammmir wrote:
       | the generics mafia has ruined rust and looks like go is next.
        
         | anothernewdude wrote:
         | I shudder to think what Rust would look like without generics.
        
       | tannhaeuser wrote:
       | Not entirely getting the hate/hype towards generics. What about
       | run-time reflection and annotations, arguably an addition with
       | more drastic consequences, and all things considered, not for the
       | better IMO. Has anyone an opinion on using GraalVM/Java vs
       | Golang?
        
       | bitwize wrote:
       | Now if they can shitcan the GC, Go might come within spitting
       | distance of being competitive with Rust.
        
       | durbatuluk wrote:
       | If you want all features of language X (I doubt we will stop at
       | generics) use language X. Stop trying to make all languages the
       | same.
       | 
       | I work with programmers from OO background (java) and they can't
       | even grasp the utility of functions as value or closures. Every
       | damn "service" has an interface/generated mock and anemic model.
       | They're desperate waiting for generics for go to "complete".
       | 
       | I fear the influx of OO programmers.
        
         | chana_masala wrote:
         | OO !== Generics, at all
        
           | durbatuluk wrote:
           | I didn't say they're the same. I'm saying people coming from
           | OO complain all the time of lack of generics, inheritance
           | (besides composition) etc.
           | 
           | I teach basic go at my job to help people wanting to migrate,
           | they start the go journey thinking go will do "less" because
           | we don't have all features as their main language. Which
           | reminds me of this phrase:
           | 
           | > 'You cannot reduce the complexity of your problem by
           | increasing the complexity of your language.'
        
       | tapirl wrote:
       | Go needs custom generics for sure. But it is really a hurry-up to
       | support custom generics for Go in version 1.18. Many problems
       | have not been resolved yet.
       | 
       | * should the builtin generics syntax be compatible with the new
       | custom syntax
       | 
       | * how many problems will be solved by the custom generics and how
       | much complexities will be added. Is it a good balance?
        
         | int_19h wrote:
         | The second question has been extensively answered by numerous
         | mainstream languages adopting generics in the past, oh, 30
         | years or so?
        
       | smokey_circles wrote:
       | Language flamewars on internet forums are... strange.
       | 
       | Why have we all so strongly coupled our identities as programmers
       | to the language we use? Sense of community and a perceived need
       | to defend it?
       | 
       | I don't think Go needs generics, but I'm not about to invent
       | obscure edge cases to justify for/against the idea. That's a
       | recurring theme in all defenses of any language. It's not
       | helpful.
       | 
       | Use Go if you like the "clarity", stay away from it if you don't
       | like the "verbosity".
       | 
       | These are both valid points, but they're subjective. Pushing it
       | as fact is dishonest and self-serving, as well as eventually
       | detrimental.
        
         | kodah wrote:
         | I think this derives from the fact that a fair amount of
         | programmers are told what language they will write in and are
         | forced to adhere to the languages semantics even if they liked
         | other language semantics.
         | 
         | The force part comes from a desire for business continuity and
         | efficiency. If you're a large scale Go shop there's a fair
         | amount of specialized infrastructure needed including a goproxy
         | to prevent leakage, some apparatus to view documentation, and
         | probably educational resources.
         | 
         | A large scale Java shop needs extensive artifact storage and a
         | place to host generated Java docs.
         | 
         | If you employ both languages your infra cost is now going up
         | for something a business sees as pure overhead rather than the
         | conduit for innovation. In my experience this leads to language
         | supremacy discussions, bickering over scarce funding, etc.
         | 
         | On my team, we're polyglot. Everything, including docs, are
         | generated and self-hosted internally. We make the best of a
         | brisk situation. What lets me sleep okay at night is that
         | developers have a choice to use the best tool (language) for
         | the job, not just the one that a company hired for ten years
         | ago.
        
         | Abishek_Muthian wrote:
         | When I started programming in Go after a decade of Java[1], I
         | found it painful to not code without generics but then over the
         | past couple of years I've become used to it.
         | 
         | I understood the philosophy of Go and why it didn't have
         | generics or may be I'm just convincing myself of that because
         | I'm invested in it. I think when you accept the philosophy of
         | something you already get coupled into it.
         | 
         | I don't really have an opinion about Go bringing in generics, I
         | would use every time saving feature available in a programming
         | language. On the other hand I really hope additions like these
         | doesn't become a point of friction among those who really have
         | an opinion, Especially those who have been contributing to Go
         | and end up forking Go.
         | 
         | [1] https://abishekmuthian.com/i-had-to-let-go-of-java/
        
         | chrismarlow9 wrote:
         | For me it's about paradigms the language represents. I try to
         | extend the simplicity of golang all the way to the network
         | architecture. I've learned that it's better to build many very
         | very simple things and connect them. Not for any technical
         | reasons, but because it allows other developers to quickly
         | begin adding to and fixing your systems. You get to leverage
         | the large amount of mediocre programmers when your systems are
         | simple instead of looking for heros. It's definitely easier
         | said than done though to make systems naturally intuitive and
         | simple.
         | 
         | I've also learned that in most cases you don't need to invent
         | some giant application. It's far easier to create extensions or
         | wrappers to existing operations or service tools, with a bonus
         | (again) being easier hiring and delegation. You can hire
         | someone who knows a standard piece of tech and quickly ramp
         | them up on a small extension or wrapper that you wrote. Golang
         | is the language that made me always take this simple approach
         | first and look for something that does 80% of what I need and
         | think about problems very generically.
        
           | dolni wrote:
           | > I've learned that it's better to build many very very
           | simple things and connect them. Not for any technical
           | reasons, but because it allows other developers to quickly
           | begin adding to and fixing your systems. You get to leverage
           | the large amount of mediocre programmers when your systems
           | are simple instead of looking for heros. It's definitely
           | easier said than done though to make systems naturally
           | intuitive and simple.
           | 
           | Creating a bunch of microservices and connecting them has
           | just moved your complexity from the "monolithic app" kind to
           | the "integration" kind. It's much harder to understand the
           | potential impact of your changes when "anything" could be
           | using a service via the network.
           | 
           | It's a trade off here. If you have integration complexity,
           | you need integration heroes.
           | 
           | > I've also learned that in most cases you don't need to
           | invent some giant application. It's far easier to create
           | extensions or wrappers to existing operations or service
           | tools, with a bonus (again) being easier hiring and
           | delegation. You can hire someone who knows a standard piece
           | of tech and quickly ramp them up on a small extension or
           | wrapper that you wrote. Golang is the language that made me
           | always take this simple approach first and look for something
           | that does 80% of what I need and think about problems very
           | generically.
           | 
           | This is a great idea. Leverage industry experience when and
           | where you can. Minimize the amount of "tribal knowledge" that
           | your team requires to be effective.
        
         | toolslive wrote:
         | Go _has_ generics. They 're just not (yet) available for you.
         | So to some it feels like a Tantalus punishment.
        
           | ibraheemdev wrote:
           | If you're referring to map[K]V, that's not true. Go doesn't
           | have generics, it uses some compiler magic under the hood
           | specifically for the map type [0]. The generics proposal is
           | being implemented from the ground up.
           | 
           | [0]: https://dave.cheney.net/2018/05/29/how-the-go-runtime-
           | implem...
        
             | masklinn wrote:
             | > If you're referring to map[K]V, that's not true. Go
             | doesn't have generics, it uses some compiler magic under
             | the hood specifically for the map type [0].
             | 
             | They're not _generic_ (aka userland) generics, but they 're
             | still generics: parametric types, and functions able to
             | work on them generically (you don't have a separate
             | `append` function for every type you might put in a slice).
             | 
             | > The generics proposal is being implemented from the
             | ground up.
             | 
             | Of course it is, the builtins are ad-hoc and half-assed.
             | That doesn't mean they ain't a thing.
        
           | valenterry wrote:
           | That's not what anyone means when they say that a programming
           | language has generics.
        
         | 13415 wrote:
         | There is no doubt that Go needs generics. Pretty much every Go
         | container and data structure library on github will benefit
         | from generics. The empty interface is used _everywhere_ ,
         | leading to all kinds of panicking typecasts, hard to debug
         | errors, and inefficient conversions. The vast majority of these
         | uses can be made type-safe, more efficient, and clearer with
         | generics. There is nothing subjective about the benefits of
         | generics. Together with type-safe enumerations I miss generics
         | the most from Ada.
         | 
         | To be honest, I'd use Ada if it had a significant
         | infrastructure, but it feels pretty much dead. With Go I can at
         | least get 3rd party libraries, as long as I check the source
         | code to see if it's good enough.
        
           | wvh wrote:
           | There's some pain in writing generic data structure
           | algorithms for sure. It would have been an interesting
           | experiment though if the Go authors would have tried to
           | improve the tooling around code generation and making it
           | easier to use, as an alternative avenue to generics as code
           | generation might satisfy some of the cases likely to trigger
           | those complains.
           | 
           | Anyway, interesting to see how far they will take the
           | generics in the path to Go 2.
        
             | pjmlp wrote:
             | It isn't as if previous languages did not used code
             | generators before generics were a thing on them.
        
         | Zababa wrote:
         | > Why have we all so strongly coupled our identities as
         | programmers to the language we use?
         | 
         | Because the viability of a language is linked directly to its
         | ecosystem and big names using it, so people that want to use
         | one language have to promote its use if it's not in the top 5.
         | You don't see many people advocating for Java, but some people
         | are advocating for C#, Kotlin, Scala. You don't see many people
         | advoating for JS, but many people are advocating for Elm,
         | TypeScript, ReasonML.
         | 
         | On the other hand, people that are "forced" to use a language
         | want to bring features from other languages they'd rather use.
         | You can see in this graph
         | https://go.dev/blog/survey2020/missing_features.svg (from
         | https://go.dev/blog/survey2020-results) that people that want
         | Go to change want to bring features from ML, Java, Rust, etc.
         | Other languages. Because they have to work with Go or want to
         | work with it but want to bring what they already know with
         | them.
         | 
         | Lots of people spend 8 hours a day using the programming
         | language that their company chose. Adding a few things that
         | they like to it seem like a good way to make their life better.
        
         | rowanG077 wrote:
         | How is it strange? It seems completely natural to me. A
         | programming language is a tool that software devs have to use
         | for 8 hours a day. And even more annoyingly the individual
         | software dev generally doesn't get to decide what tool he gets
         | to use. That means the top programming languages are always
         | under a strong pressure to adopt feature X from Y devs
         | favourite language. Now Go is quite an interesting case I
         | think. It's essentially an ancient language with good tooling
         | support backed by one of the largest companies in the world. Go
         | has now yielded to generics. I don't think Go is capable of
         | becoming modern because the initial design decision have
         | essentially made that almost impossible. I wonder though, what
         | the next feature for Go demanded by the community will be.
        
       | brundolf wrote:
       | I've never used Go, and from the outside I take a lot of issues
       | with its design choices.
       | 
       | But even without having used it I always thought the lack of
       | generics was very interesting and I could see how it was
       | desirable. It's fascinating to me that Go has gotten as far as it
       | has without them (proving that it's possible to), and the mindset
       | shift people describe having around them seems like a really
       | important thing to pay attention to.
       | 
       | One thing I'm curious about: user-defined generics I can see
       | going without, but the core language and standard library surely
       | need to have them. How does that work in practice? Is there a
       | syntax for using them and just not one for creating them? How are
       | they defined in standard library code?
        
         | 4ad wrote:
         | > It's fascinating to me that Go has gotten as far as it has
         | without them (proving that it's possible to), and the mindset
         | shift people describe having around them seems like a really
         | important thing to pay attention to.
         | 
         | Yes, the mindset of the people was certainly a key part of
         | this, but another key part is that Go has interfaces, which are
         | existential types, which are dual to universal types
         | (colloquially called generics). If the type system is
         | expressive enough (System Fo), you can express one in terms of
         | the other. Of course, Go's type system wasn't expressive enough
         | to realize the true duality, but it was expressive enough to
         | express _many_ things people would have used generics for in
         | other languages.
         | 
         | Other languages which don't have generics don't have
         | existential types either, and people see Go through that lens
         | and don't understand how we got anything done. Well put on some
         | existential glasses.
         | 
         | As an aside, one of the reason it was so hard to develop a good
         | design for generics is that they inevitably interact with
         | interfaces, precisely because of the duality above.
         | Unfortunately, the non-language experts who complained on web
         | forums about the lack of generics in Go for the past 11 years
         | do not understand what that means, but that didn't stop them
         | from complaining. Let me put it another way. There's a reason
         | why Rust traits are not types, but Go interfaces are types.
        
           | masklinn wrote:
           | > Yes, the mindset of the people was certainly a key part of
           | this, but another key part is that Go has interfaces, which
           | are existential types, which are dual to universal types
           | (colloquially called generics).
           | 
           | The biggest reason was probably that it had bespoke generics
           | for a bunch of core collections, significantly mitigating the
           | need for userland generics.
           | 
           | Without the builtin generic slice, map, and channel, the
           | issue would have been significantly less tenable on both
           | efficiency and convenience fronts.
           | 
           | It's not like "we have interfaces and we still need generics"
           | is a new thing.
        
             | 4ad wrote:
             | This argument is often repeated but doesn't make any sense.
             | 
             | The value of generics is quantifications over types. In
             | particular univeral quantification. "Generic" slices don't
             | give you that, because the values are "generic", but there
             | are no non-static type constructors. Go slices are
             | "generic" only in the same sense than arrays in C are
             | generic, or (if we go to the degenerate case) that a
             | variable is "generic" because you can declare it with any
             | type. I'm sorry, what?
             | 
             | Go has existential quantification, something which C lacks.
             | Go is very unusual that it started with existential types.
             | Languages based on System Fo have universal quantification
             | as a native operation and implement existential types as
             | higher rank universals. The fact that Go had existentials
             | from the beggining is not some technical nitpick, it is
             | what gives it type-level expressive power over languages
             | like C. Ignoring this in arguments about generics is
             | missing the point completely.
        
         | masklinn wrote:
         | > How does that work in practice? Is there a syntax for using
         | them and just not one for creating them? How are they defined
         | in standard library code?
         | 
         | They're special-cased in the compiler, with bespoke
         | implementations.
        
         | skybrian wrote:
         | There are the usual operators and special functions like
         | append(), which is implemented in the compiler and works on
         | arbitrary slices. Not many of them, though.
         | 
         | They are defined in the _builtin_ pseudo-package:
         | https://pkg.go.dev/builtin
        
         | takeda wrote:
         | Java didn't have generics until version 5. They were added 8
         | years later.
        
           | masklinn wrote:
           | c# was also released without generics, they wanted it out the
           | door and the generics were not ready. They landed in 2.0.
        
           | int_19h wrote:
           | Java didn't have user-defined generics, but it did have
           | parametrized builtin types: arrays. Same thing for C#.
        
       | jagger27 wrote:
       | Pretext: I love Go and write most of my day job code in it.
       | 
       | To the people moaning about how generics will make their
       | favourite language as awful and ugly as Java: all of the
       | libraries and techniques you like and use today will always work.
       | Little things like sorting will use generics pretty much
       | transparently. All of the strongly typed code you write today
       | that receives and returns concrete types will be just as valid
       | tomorrow as it is today. Interfaces keep the same semantics and
       | are a core part of how generics work.
       | 
       | I think it's important to remember that the people who design
       | this language like it for the same reasons you do.
        
         | masklinn wrote:
         | > To the people moaning about how generics will make their
         | favourite language as awful and ugly as Java: all of the
         | libraries and techniques you like and use today will always
         | work.
         | 
         | In fairness: just because that's true doesn't mean the
         | libraries they like or need won't be migrating to generic
         | facilities one way or an other, so they may be forced to the
         | choice of interacting with generics or needing to reimplement
         | their wheels (though also in fairness that's also common in the
         | go ecosystem).
         | 
         | > I think it's important to remember that the people who design
         | this language like it for the same reasons you do.
         | 
         | That's not necessarily true, the designers of the language are
         | not necessarily designing it for their use or like. See: Rob
         | Pike's well known quotes on the target population for Go.
        
       | evanmoran wrote:
       | This is actually my first week using go (from years of
       | C++/Swift/js/etc) and I've been very impressed with the module
       | system and simplicity so far. I'd definitely encourage others to
       | try it if they haven't.
       | 
       | As for generics, Go's lack of function overloading and arg
       | default values is really interesting. It ensures that a function
       | is always easily found as it's the only thing in the module with
       | that name. I'll be curious to see if generics are easier to
       | follow without function overloading. It will still be only in one
       | place, where as in C++ you could have hundreds of functions with
       | the same name across many libraries and you just have to hope
       | your ide knows which to step into.
        
         | masklinn wrote:
         | > As for generics, Go's lack of function overloading and arg
         | default values is really interesting. It ensures that a
         | function is always easily found as it's the only thing in the
         | module with that name. I'll be curious to see if generics are
         | easier to follow without function overloading.
         | 
         | There are already a number of langages with generics and
         | without overloading (or defaults). Haskell, ocaml, rust, ...
        
           | 4ad wrote:
           | True of OCaml and Rust (and many others), but Haskell
           | certainly has overloaded functions through type classes. In
           | fact, once OCaml gets implicit modules, this won't be true
           | anymore of OCaml either.
        
             | masklinn wrote:
             | > True of OCaml and Rust (and many others), but Haskell
             | certainly has overloaded functions through type classes.
             | 
             | That's no more overloading than Rust has through traits.
        
               | 4ad wrote:
               | It absolutely is, because class methods in Haskell are
               | top level declarations. Not only this is not true in
               | Rust, but it doesn't even matter as Rust doesn't have
               | polymorphic values, only polymorphic types and functions.
               | 
               | In Rust, unlike in Haskell or ML type inference stops at
               | function boundary.
        
       | [deleted]
        
       | mgraczyk wrote:
       | Glad to see this finally happening. I've been writing a decent
       | amount of Go lately and there are plenty of instances where this
       | will make the code more readable.
        
       | silisili wrote:
       | Not to be contrary for its sake, but I'll say this is one change
       | I'm really not happy about.
       | 
       | I feel like it's a change to placate many, while driving a lesser
       | amount away. Which is fine, but still feels like the end of
       | something, as I am one of the aforementioned 'lesser.'
       | 
       | As for why...I love above most the simplicity and readability of
       | Go. Any change which encroaches that, which this does, is a net
       | negative to me.
        
         | nerdwaller wrote:
         | I fully agree, after writing go for the last 7 years. I
         | recognize that generics solve some problems, but there's a cost
         | in doing so. In that period I've had only a few cases where I
         | wish I was back in a language with this feature (Java being my
         | previous typed language), however most of the time the
         | interface with an application specific data model was more than
         | sufficient. Obviously you need to wrap that abstraction for
         | typesafe code, but that's pretty trivial.
        
           | vorpalhex wrote:
           | Without generics, I have seen terrible and unreadable golang
           | code. There is no tool that can not be mis-used.
           | 
           | Generics are adding a tool to the toolbox. They can be used
           | well or they can be mis-used. I recently wrote a gui app in
           | Golang using Fyne and I really wish I'd had generics for some
           | of the UI handling - instead I ended up having to write some
           | really ugly and not simple code to handle the case. The end
           | result was worse and less-simple than if I had been able to
           | use generics.
        
             | jshen wrote:
             | Can you give an example of terrible unreadable go code due
             | to a lack of generics? I've grown to love go because it's
             | one of the few languages where I can jump into a new code
             | base and relatively easily understand what is going on.
        
               | kmm01 wrote:
               | Because you will already have seen that precise piece of
               | code in a thousand other contexts?
        
               | dmitriid wrote:
               | > Can you give an example of terrible unreadable go code
               | due to a lack of generic
               | 
               | https://news.ycombinator.com/item?id=28254411
               | 
               | The "solution" to this is copy-pasted boilerplate code
               | with casting for every call.
        
             | theshrike79 wrote:
             | I have seen terrible and unreadable generic code, people
             | building abstractions just for the sake of abstractions.
             | 
             | Hello-world level projects with 20 class deep hierarchies
             | of generic classes, just to make it "generic" in case you
             | need it later.
        
               | doctor_eval wrote:
               | I agree. It's true for all languages. I once had to
               | untangle a small Java app that had about five packages
               | with two classes per package (I refactored it into a
               | single package).
               | 
               | Some people will abuse generics, no doubt, just like my
               | colleague abused packages. But Go has such a strong
               | culture around idiomatic code that I'm not too worried
               | that generics are the end of the world. In fact, I don't
               | like keywords like "append" and I'm hopeful generics will
               | replace them.
               | 
               | TBH I was more upset about the Go 1.17 ability to panic
               | during a type conversion from slice to array pointer.
               | That one really grates my gears.
        
         | anothernewdude wrote:
         | No generics, and lack of error handling are why I bounced off
         | Go.
         | 
         | Can I write a generic data structure? No. You have to cast from
         | interface{}.
         | 
         | Java 1.4.2 is dead, and rightly so.
         | 
         | And manual error checking? No. Get that garbage out of my
         | control flow. I'm not going to a language that has worse error
         | handling than C. At least in C you can factor it out.
        
           | Gibbon1 wrote:
           | Writing stuff in C... one thing I would like is an error
           | return keyword. And the ability to set how you'd like
           | unhanded errors to be dealt with. Like unhanded error means
           | program aborts. Let the programmer decide how sloppy he wants
           | to be.
        
         | kbenson wrote:
         | Either a language changes to keep interest up and bring in a
         | new audience, or it's left behind by advances to and the status
         | quo (and what's considered a minimum set of features) and
         | stagnates.
         | 
         | Just look at Perl. Stuff written 20 years ago is likely to work
         | without change on the newest release more often than not. For
         | certain work contexts, like system utilities and long life core
         | programs, this can be amazingly useful.
         | 
         | And all it will cost you is the slow decay of your community
         | until eventually they're almost all gone, and nobody releases
         | supported libraries for you anymore, and there's not even
         | enough community left to provide community support for many new
         | services and technologies.
         | 
         | If you stick around one thing long enough you're destined to be
         | disappointed one way or the other.
        
           | adamlett wrote:
           | C
        
             | kbenson wrote:
             | C is only used because it has a widely deployed set of
             | libraries and by it's nature as an underpinning of most
             | foundational software because it was the language of choice
             | when we really started hitting exponential growth in
             | computing. If there wasn't an _enormous_ set of software
             | and source code out there for it already, would there be
             | any reason to use it over anything else?
             | 
             | And even then it's latest language standard update was in
             | 2018. You still have to deal with the fact it's changing
             | and keep up with it if you plan to read or use others code.
             | And of you don't, then you can safely not care about
             | advances in C, just as you can safely not care about
             | changes in Go.
        
             | tephra wrote:
             | C11 introduced type generic expressions.
        
               | c-cube wrote:
               | Not in the commonly understood sense of "generics", no.
               | You get to switch on a type, but you don't have generic
               | functions or types. A reusable, type-safe Vec or HashMap
               | are still not possible in C...
        
             | pjmlp wrote:
             | ISO C23 is coming up, and until the last UNIX stops
             | working, C's existence is assured.
        
             | Zababa wrote:
             | To add to what other people said, the tooling around C has
             | changed a lot since C was created, partially because
             | there's already so much code in C. The Linux kernel is
             | 20/30 millions lines of code of C mostly, Kubernetes is
             | below 2 millions. So at this point you can still change the
             | language a bit. With C it's harder, so instead people
             | invest in tooling (and replacements).
        
           | pjmlp wrote:
           | For some strange reason many developers lose sight that
           | programming languages are software products just like
           | anything else than one can sell for installing into a
           | computer.
           | 
           | While FOSS might have changed the way to sell those products,
           | they are still products looking for attention, market share,
           | ecosystems, conference talks, consultancy, trainings.....
        
         | bogota wrote:
         | If i wanted or needed generics i would use another language. I
         | have been able to write great code without them for 5 years now
         | though. But now i get to defend my codebases from the unneeded
         | introduction of them from largely developers who think they are
         | too smart.
        
           | silisili wrote:
           | Same here. But I think it's more laziness than 'too smart.'
           | 
           | I like to liken it to house construction. Imagine if a number
           | of people demanded that natural gas and water be combined.
           | Why do I have to make two separate pipes? They even look the
           | same!
        
             | jolux wrote:
             | There are just things you can't do without having generics
             | in your language. User-defined collections, for one.
             | Statically typed higher order functions, for another. To
             | paraphrase (I believe) Bob Harper, you either have a
             | statically typed language with generics, or you have a
             | dynamically typed language. That's the result of not having
             | generics. Code that needs them becomes more dangerous and
             | error-prone.
        
           | takeda wrote:
           | You can totally do fine without generics depending what you
           | do. It mostly affects code that supposed to be reusable,
           | especially libraries.
        
           | lamontcg wrote:
           | you sound like you're too smart for generics.
        
             | bogota wrote:
             | No I'm likely too dumb for them but my code base is clean
             | and easy to onboard people to. I take great pride in new
             | hires telling me something is easy to do after only working
             | in it a week
             | 
             | And like i said generics have a place its just a way
             | smaller place than many people think
        
         | infogulch wrote:
         | I can sympathize with this concern; constraints can force
         | authors to just write simpler code which has some very nice
         | benefits. But that leaves out some legitimate use cases like
         | collections that were terribly served by genericless-go.
         | 
         | Yes there will be some pockets of libraries where authors take
         | generics to an extreme. Besides being a bit of fun, it's good
         | to explore the edges of what you can do with the language, so
         | this exercise will be valuable even if you don't use them
         | regularly in your projects.
         | 
         | But I don't really see pervasive gratuitous use of generics
         | becoming a big problem for the average lib, Go devs tend to
         | lean practical on potentially abused features like this, and
         | there will be many users like yourself that will still prefer
         | simpler interfaces. I guess we'll see over time.
         | 
         | Really, Go's lack of generics for so long wasn't an ethos
         | (despite many taking it that way) but more that the right
         | implementation just hadn't revealed itself yet. I think the one
         | they chose is a pretty good match for Go, and I hope that it
         | makes Go more complete.
        
         | _wldu wrote:
         | I agree about placating. Go is fine as it is. I don't need or
         | want generics, but the addition of generics won't stop me from
         | using Go.
        
           | silisili wrote:
           | It might me, in time. As mentioned, my main interest in Go is
           | in how easily I can read others code. This kinda ruins that,
           | even if I never use it.
        
             | tengbretson wrote:
             | Learning something is also an option.
        
               | jshen wrote:
               | Learning things outside of complex computer science
               | topics often adds more value to the world. The ability to
               | write useful programs without dedicating ones life to
               | esoteric comp sci topics is a net positive for the world.
        
               | rustc wrote:
               | Are generics really considered as "esoteric comp sci
               | topics"?
        
               | Gibbon1 wrote:
               | I needed to use C# for some project. Used generics
               | without actually being aware what they were. Helps that
               | C# implements generics without type erasure.
        
               | masklinn wrote:
               | > Helps that C# implements generics without type erasure.
               | 
               | For about 95% of "using generics" that makes no
               | difference, and you'd have had no more issue in Java.
               | 
               | That aside, Go is implementing reified generics (there is
               | no real backwards compatibility concern as the "core"
               | collections are already ad-hoc parametric types, and the
               | rest is not a great loss).
               | 
               | Java had a lot more legacy code using a much higher
               | number of standard but not-generic-at-all collections,
               | I'd bet there were also concerns around the forward
               | compatibility of legacy reflection code, and they'd
               | probably considered a lot of collections-related goodwill
               | spent with Java 1.2's Collections Framework and the
               | deprecation of the limited set of original collections.
        
               | jshen wrote:
               | If you want coding to be accessible to people without
               | comp sci degrees, and those who are NOT employed as full
               | time developers.
        
               | c-cube wrote:
               | If people can understand functions, they can understand
               | generics. Nothing more complicated, generics are just
               | functions on a few type arguments.
        
               | jshen wrote:
               | Here's an example from this very thread that shows how
               | complex generics get relatively quickly.
               | 
               | https://news.ycombinator.com/item?id=28255738
        
               | jagger27 wrote:
               | That example is essentially the most basic use of
               | generics. There are much more complex examples that would
               | support your argument better.
               | 
               | What do you find confusing about that code?
        
               | aslkdjflkajsdf wrote:
               | I learned C++ when I was 13, Haskell at age 15. I don't
               | have a CS degree nor do I work as a developer.
        
               | jagger27 wrote:
               | I'm not sure Go has ever been a great language for non-CS
               | people, but it's been a very long time since I was new to
               | programming. Go is pretty clearly a "get shit done"
               | language catered to developers: a productivity tool. Why
               | should it have its capabilities restricted?
               | 
               | English is used in both reality TV shows and scientific
               | journals. The vocabulary used in the latter doesn't
               | prevent it from being useful in the former.
               | 
               | Go will still be usable the exact same way it is today
               | after generics are brought in. It's not like all the
               | existing more approachable code written without generics
               | won't just disappear overnight.
               | 
               | That said, I agree with GP. Generics aren't that complex
               | anyway.
        
               | silisili wrote:
               | Thank you.
        
           | dmitriid wrote:
           | > I don't need or want generics
           | 
           | I do need and want generics. So... Whose needs and wants are
           | more important?
        
             | silisili wrote:
             | Neither, of course. I'll leave so you can join. I don't
             | think either of us is wrong.
        
               | AnimalMuppet wrote:
               | You sound like, for you personally, generics are like a
               | poison atmosphere. You simply can't live in that
               | environment.
               | 
               | Why? Why so negative?
               | 
               | I work in C++. Generics exist there. I don't use them
               | except for some STL containers. I just... don't use them.
               | I don't have problems where I need them. How does it hurt
               | me if they exist?
               | 
               | You may say that someone else will use them, and make
               | your code more unreadable. They may, but... if they
               | really help the code base, use them. If they don't and
               | someone uses them anyway, teach them some taste and
               | discernment. If they can't learn, then you've got worse
               | problems than a language that has generics.
               | 
               | If it's borderline, but against your personal taste, then
               | yeah, you're kind of out of luck. On the other hand,
               | personal taste changes over time, often from experiencing
               | new things. You could try it for a while, and see how it
               | goes...
        
               | silisili wrote:
               | I don't mean to be negative only, and appreciate your
               | reply.
               | 
               | But I know what happens in real codebases. Before long,
               | scammy tutorials pop up showing Go as an essentially
               | dynamic language, and that's what bootcampers write. As
               | of today, they are forced to write simple, boring code.
               | 
               | I never mind a carefully added thing, for carefully
               | thought of situations, as this probably was.
               | 
               | The problem is that I see the abuse from here. And even
               | if not abuse, it changes how you approach problems. And
               | approaches matter as much or more then spec.
               | 
               | I knew a person who insisted on a lot of things when
               | working in a Go code base...one of which was mixed typed
               | tuples. It was ugly, awful code of interfaces all the way
               | down. It's ugly and Go let you know that. A voice of
               | reason would say...what are you doing? That's not how you
               | do it in Go.
               | 
               | Readability goes beyond the syntax. It's a mindset. And
               | now it's not.
        
               | rustc wrote:
               | > Before long, scammy tutorials pop up showing Go as an
               | essentially dynamic language
               | 
               | Sorry are you saying adding generics to Go makes Go
               | closer to dynamic languages? Shouldn't that be the
               | opposite?
               | 
               | > I knew a person who insisted on a lot of things when
               | working in a Go code base...one of which was mixed typed
               | tuples. It was ugly, awful code of interfaces all the way
               | down. It's ugly and Go let you know that. A voice of
               | reason would say...what are you doing? That's not how you
               | do it in Go.
               | 
               | Do you have an example of this (code)? What's wrong with
               | tuples with elements of different types? What's the
               | alternative?
        
               | masklinn wrote:
               | Go doesn't even have tuples, where would those even come
               | from?
        
               | silisili wrote:
               | So, mixed typed tuples was the idea, but Go doesn't
               | support either of those things, so it ended up as a
               | [][10]interface{} or some such. So for each item in the
               | slice, type assert all 10 things inside the subarray.
               | Luckily the comments had a key of expected types of each.
        
               | riwsky wrote:
               | Your problem isn't generics or any other language
               | features; your problem is a lack of effective code review
               | or technical leadership.
        
               | djur wrote:
               | It sounds to me like the simplicity of the language in
               | this case didn't prevent a bad programmer from writing
               | bad code, and that it was a problem that should have been
               | addressed with code review and training, not by expecting
               | the language to keep things in check.
        
           | mountainriver wrote:
           | I didn't need generics till I wrote a mathematical library,
           | and wow they would be handy
        
             | _wldu wrote:
             | I've used templates in C++ to do that and I agree that it
             | is handy. I had to write far fewer functions than I would
             | have without them. Sometimes, it's nice to not care or
             | worry about how many bits are in a number.
        
         | flippinburgers wrote:
         | I agree with you strongly. No generics please. It is already
         | hard enough to try to steer a group of developers towards a
         | shared vision without giving them the ability to show off how
         | "smart" they are.
         | 
         | Abstractions in libraries? Ok maybe.
         | 
         | In the higher level code that the vast majority of programmers
         | actually write? No. Thank. You.
         | 
         | Besides, interfaces cover the majority of generic problems on
         | the ground.
        
           | mikepurvis wrote:
           | Isn't that a fairly easy policy to enforce, though? Basically
           | you blanket ban them in your linter, and only create
           | exceptions for specific cases like containers, parsers,
           | situations where it saves you a cast, whatever.
           | 
           | I know that doesn't help you when you have to interact with
           | the larger Go ecosystem on Github, but at least within an
           | org, it shouldn't be terrible. Certainly the culture of
           | golang is well established-- millions of lines of it have
           | been written generic-free, so I'd expect that it will only be
           | applied where it really is an obvious improvement.
        
         | lokedhs wrote:
         | Back when generics were introduced to Java I felt the same
         | thing. I had been doing Java for years at that time. I had also
         | been working for Sun, so of course I was exposed to it.
         | 
         | I was very negative towards generics and had similar arguments
         | as you. It didn't take long before I changed my mind. I'd never
         | want to write Java without generics again.
         | 
         | I'm not saying you're going to have the same experience, but I
         | would suggest you give it a try before dismissing its value.
        
           | pkulak wrote:
           | Does Go generics have type erasure? If not, OP can expect and
           | even better journey.
        
             | 4ad wrote:
             | There are two meanings of "type erasure". One concerns the
             | user, the other the compiler writer.
             | 
             | When most users people ask about type erasure, they ask
             | whether types are erased when compiling the reflection
             | information for polymorphic values (like Java does). Go
             | doesn't have polymorphic values, so the question doesn't
             | apply.
             | 
             | Type erasure means something more general than that to
             | compiler people. Type erasure refers to whether you can
             | compile code while erasing its type, and it's generally a
             | useful property. In general statically-typed programming
             | languages are implemented with type erasure, while
             | dynamically-typed languages are not. Of course, since Go
             | has reflection, it can't do type erasure. Interfaces also
             | conflict with type erasure somewhat, though as expected,
             | during the code generation types are erased as much as
             | possible.
             | 
             | As a comparison, Rust does type erasure fully.
        
               | iso8859-1 wrote:
               | So Haskell has type erasure only for data types that do
               | not derive Typeable?
        
               | tome wrote:
               | No, because all types have a Typeable instance! Haskell
               | has type erasure, and then using Typeable adds the type
               | information back exactly where it is needed.
        
             | mseepgood wrote:
             | No, they don't have type erasure.
        
               | erik_seaberg wrote:
               | Go is getting monomorphization, separate machine code for
               | each type specialization of a generic function. I assume
               | reflection will choose the one for the args you want to
               | pass, or make you do that.
        
               | masklinn wrote:
               | > I assume reflection will choose the one for the args
               | you want to pass, or make you do that.
               | 
               | According to the spec:
               | 
               | > It's impossible for non-generic code to refer to
               | generic code without instantiating it, so there is no
               | reflection information for uninstantiated generic types
               | or functions.
               | 
               | You won't be able to reflect a generic List or List[T] at
               | all which... makes sense, I think? `reflect` works on
               | values at runtime, so it necessarily works with
               | instantiated types as you can't have a value of an un-
               | instantiated (generic) type: what would you give to
               | `reflect.TypeOf` which could return an uninstantiated
               | generic type?
        
               | erik_seaberg wrote:
               | I was thinking of generic functions rather than (non-
               | generic) methods on generic types. Unfortunately it looks
               | like reflection can't look up functions in a module _at
               | all_ , which is surprisingly broken.
        
               | masklinn wrote:
               | > Unfortunately it looks like reflection can't look up
               | functions in a module at all, which is surprisingly
               | broken.
               | 
               | The more time passes the more I think ubiquitous
               | reflection in statically typed languages is what's broken
               | (and a reflection (heh) of deep limitations of the
               | language).
               | 
               | So while I could understand having issues with generics
               | breaking existing reflection code (which doesn't seem to
               | be the case), I'm not going to be sad over reflection
               | having never supported toplevel functions in the first
               | place.
        
               | erik_seaberg wrote:
               | What good are top-level functions if they're unreachable
               | from any script interpreter or management RPC server or
               | other languages' FFI?
        
               | masklinn wrote:
               | I fail to see what any of this has to do with reflection.
               | 
               | > any script interpreter
               | 
               | What are you even talking about.
               | 
               | > or management RPC server
               | 
               | I would very much expect RPC endpoints to be opted in
               | explicitly and statically.
               | 
               | > or other languages' FFI?
               | 
               | I fail to see why Go-level reflection would be involved
               | in that in any capacity.
               | 
               | > What good are top-level functions
               | 
               | You can call them? From your go code?
               | 
               | Are you saying rust or C can't be because they don't have
               | reflection? That's a strange position.
        
               | 4ad wrote:
               | Functions are useful because you can call them from your
               | program.
        
           | mypalmike wrote:
           | With Java, I didn't find it to be either a huge win or a
           | major loss. And I still don't. It's basically window dressing
           | that lets you avoid casts in certain obvious places where
           | they weren't particularly problematic anyhow.
        
             | hyperman1 wrote:
             | It's more than window dressing. A year ago I added correct
             | generics to about 50 000 lines of Java, an old module in a
             | bigger program. The change was mostly mechanical, removing
             | casts and adding signatures.
             | 
             | I found a few places where refactoring had left behind a
             | wrong type cast. Production logs demonstrated actual
             | crashes corresponding to these cast. There were bugs in the
             | issue tracker, marked unresolvable.
        
           | silisili wrote:
           | Thanks for your experience, really. Here's hoping.
        
         | puddingforears wrote:
         | How would you write a singly linked list who's contents are
         | arbitrary? What if you were to map a function over it? Say you
         | want to use this data structure with third-party objects? How
         | do you do that right now?
        
           | bouncycastle wrote:
           | Singly linked lists are something from CS1 where you learn
           | about data structures. You rarely use them in practice. In
           | most cases slices and maps do the job fine.
        
             | dilyevsky wrote:
             | They also have absolutely terrible performance due to poor
             | cache locality and putting pressure on GC
        
               | bouncycastle wrote:
               | Source?
        
               | mseepgood wrote:
               | CS201
        
               | puddingforears wrote:
               | They make a great stack, though. Cheap to use and easy to
               | implement.
        
               | [deleted]
        
               | snovv_crash wrote:
               | Use a deque at least and amortize the heap allocations...
        
               | puddingforears wrote:
               | With generics I could justify the extra engineering work
               | to make such a deque!
        
           | coryrc wrote:
           | Nobody needs to do that, but it would be nice to have sorted
           | collections without dynamic casting or rewriting half of
           | leetcode in every project.
        
           | Taek wrote:
           | Find a different way to solve the problem. I've written close
           | to half a million lines of code in Go and the lack of
           | generics has been a pain point in maybe 1% of that? Usually,
           | if you are thinking about generics you are reaching for
           | abstraction when you don't need to be.
           | 
           | If you really need generic structures you can use the
           | interface type but generally there's a simpler solution that
           | doesn't require generics.
        
             | tengbretson wrote:
             | Maybe you could have gotten that work done with fewer than
             | 500,000 loc if you used a language with a better feature
             | set.
        
               | Taek wrote:
               | Lines of code is a complete red herring. It takes me less
               | time to read and review 500 lines of Go than it does 100
               | lines of JavaScript.
               | 
               | Sometimes - especially in other languages - you see a
               | piece of "elegant" code that does something complex in
               | line 3 lines, and you think "hmm, this is a puzzle, and
               | I'm going to be staring at it for 20 minutes before I'm
               | convinced that its 100% correct."
               | 
               | We actively tell our engineers not to be clever. Write
               | boring code that is obviously correct, and don't worry if
               | your boring code is 25 lines when the elegant code is 8.
               | It takes you longer to write the elegant code, and it
               | takes the reviewer longer to read it, and often times
               | (though not always ) it's also more difficult to test.
               | 
               | I love Go because of how boring and consistent and easy
               | to read it is. The language and the task of "programming"
               | melt away and instead you get to focus on solving
               | problems.
        
               | jshen wrote:
               | And it would have been far harder to read for those new
               | to the generic code base. Complex abstractions make
               | people feel smart, they rarely make code easier to
               | understand or maintain.
        
               | aptenoforst wrote:
               | How is a generic data structure a COMPLEX ABSTRACTION?
        
               | jshen wrote:
               | They are complex. I'm guessing you haven't thought about
               | them much beyond the trivial use cases.
        
               | h4x0r12345 wrote:
               | No, it's relative. For the top 5% - 10% of developers,
               | generics are a useful tool for doing their job
               | efficiently. For the bottom 50% of developers, generics
               | are complex and confusing, and only provides more
               | footguns.
        
               | citrin_ru wrote:
               | For 0.5%-1% C++ is a powerful tool which allows to
               | quickly (thanks to rich abstractions) to write high-
               | performance code.
               | 
               | For merge mortals it is a tool hard not to misuse full of
               | hidden traps and debugging of code written even by the
               | very best developers (surprise - it has bugs too) is a
               | challenge.
               | 
               | Go just did a step towards C++, even if a tiny one.
        
               | Taek wrote:
               | And the top 1% of developers know that you are most
               | productive when you stick to the simplest primitives ;)
               | 
               | I jest, but I also don't. All the best developers I know
               | strongly prefer footgun-free libraries and primitives.
               | The advantage is that you don't _need_ to spend brain
               | cycles checking and double checking that it was written
               | correctly, and when you want to make changes you don't
               | need unwind an elaborate abstraction to stretch it
               | further.
               | 
               | In martial arts (I'm a second degree black belt), the
               | third move you learn is the round house kick (turned leg
               | kick - the first two moves are the punch and the straight
               | leg kick). At the olympic level, 70% of all points are
               | scored using a roundhouse kick.
               | 
               | The other funny thing about the roundhouse kick is how
               | much you can learn from watching someone do a single one.
               | You can tell the difference between someone with 2 years
               | of experience and 3 years of experience, and you can
               | _also_ tell the difference between someone with 15 years
               | of experience and 20 years of experience.
               | 
               | The point of this story being that masters are masters
               | not because they can do elaborate techniques, but because
               | their command over the simplest techniques is
               | superlative.
               | 
               | I've found in life that this applies to pretty much
               | everything. Martial arts, programming, painting, cooking,
               | and effectively any task that definitively has some
               | people who are better than others.
        
               | h4x0r12345 wrote:
               | Generics use the type system to make the compiler check
               | the code for you. It makes the code easier to understand,
               | more correct, and concise if you use them as they were
               | intended. It avoids tedious and error prone duplication
               | of logic. Create ONE efficient debugged implementation
               | and reuse it as much as possible. The crappy workarounds
               | for generics introduce their own complications and
               | issues.
               | 
               | But I know what you mean. I've worked on Scala code for
               | years and seen less mature developers over-engineer
               | things and get way too clever with the type system. Scala
               | is a really practical and powerful industrial language
               | that requires some maturity to use the abstractions
               | sparingly. It's only good for the top 5% of developers.
               | 
               | However, Go doesn't have such a powerful type system. It
               | looks like the Go designers implemented relatively simple
               | generics. You have to draw the line somewhere. If simple
               | Go generics are too confusing and complicated then that
               | developer should probably find another job, as generics
               | are a basic concept in programming. The Go designers are
               | pragmatic people, and they've decided that relatively
               | simple generics will make things easier in mainstream
               | commercial codebases.
        
               | theshrike79 wrote:
               | If people would stick to common generic data structures
               | (like a map/list that can handle any datatype), i'd be
               | fine with abstractions.
               | 
               | But some people have a tendency to play code golf with
               | their codebases.
               | 
               | I have, for example, encountered a "generic data
               | structure" that looked like a normal linked list on the
               | surface. BUT, it actually sorted the largest three items
               | in the first 3 cells and the average in the 4th.
               | 
               | That was multiple days of work wasted because someone
               | decided to be cute with their data structures. And that
               | wasn't even the only one of such "generic" monstrosities
               | in the code.
        
               | h4x0r12345 wrote:
               | Generics (and other abstractions) are not the root cause.
               | Go was a pragmatic defence against mediocre developers.
               | The majority of developers are mediocre by definition,
               | and will abuse _any_ abstractions to create Rube Goldberg
               | contraptions and monstrosities.
        
               | carnitine wrote:
               | What does that have to do with generics? Surely they'd
               | have written the same bad code monomorphised?
        
               | bmn__ wrote:
               | So blame goes to the hammer instead of the carpenter?
        
               | Fire-Dragon-DoL wrote:
               | Well there is a valid point of abuse in abstractions. The
               | ruby world is a disaster because of the power provided
               | combined with people reaching out to all sorts of
               | abstractions the entire time for purely experimental
               | reason.
               | 
               | It's true that applicative code shouldn't need generics
               | in probably more than 90% of the times, however the lack
               | of it affects library authors quite heavily
        
               | fiddlerwoaroof wrote:
               | Optimizing for people that are new to a codebase seems
               | like a mistake to me: onboarding costs are relatively
               | minimal and finite (per developer) whereas maintenance
               | costs have no fixed bound: if generics let you exclude
               | invalid states by design (and they do: this is one of the
               | biggest advantages of parametric polymorphism vs.
               | interfaces), they will be useful for keeping maintenance
               | costs under control.
        
               | Taek wrote:
               | You definitely want to optimize for people who are new to
               | a codebase. Over enough time, the codebase grows to a
               | point where essentially _everyone_ is new to each area of
               | the code, because nobody has touched that code in 2-3
               | years and the person who wrote it may not even be with
               | the project anymore.
               | 
               | Even for your own single-person projects - if you get
               | fancy with the code, 6 months later you find it's a lot
               | harder to get back into and mess around with than if you
               | had written the code as though you were presenting it to
               | a beginner.
        
               | fiddlerwoaroof wrote:
               | You want patterns that are well-known to the maintainers,
               | but this is different from "optimizing for the new":
               | consistent idiomatic use of a library like XState or
               | Ramda in a JavaScript project can cause a high onboarding
               | cost (because the new developers don't know the library
               | well) without any corresponding ongoing cost.
        
               | jshen wrote:
               | I'm guessing you like Haskell and similar languages,
               | because that's the natural conclusion to your line of
               | reasoning.
               | 
               | I don't agree with you, but I could be wrong. There are
               | plenty of languages that are aligned with your point of
               | view. I like go because it was going a different
               | direction, and I hope that doesn't change. You can use
               | Haskell, scala, typescript, etc to get what you are
               | looking for.
        
               | sterlind wrote:
               | so as an example, I've used priority queues a lot. you
               | need them for Dijkstra.. apparently golang has a heap
               | package which lets you push and pop `interface{}`. sure
               | you can cast, and I guess people have to, but why
               | couldn't Go just call `interface{}` object or any? the
               | awkwardness of the convention suggests an unwillingness
               | to accept failure.
        
               | xh-dude wrote:
               | Parametric polymorphism is a better fit for container
               | types IMHO. There are some interesting notes here...
               | 
               | In Go prior to generics, interface{} is an escape hatch
               | less frequently needed but not necessarily much safer
               | than void*. Post generics, interface{} is suddenly more
               | useful and will be aliased by 'any'.
               | 
               | The way the std lib heap works in Go, an implementation
               | doesn't have to mention interface{}. Using the Go std lib
               | solution is about satisfying a few interfaces, defining
               | some methods for sorting and swapping over the element
               | type. The use of interface{} is internal.
               | 
               | Go's generics solution is going to have type constraints,
               | which I think will be very familiar to some and probably
               | new to others ... So, the Go generics PQ should still
               | require some constraints on elements, not 'any'thing will
               | work. I've really enjoyed constraints in languages and
               | it's not quite natural in C++/Java, but Go's interfaces
               | already do some 'constraint' work conceptually and can be
               | used as constraints in Go's generics syntax. I'm
               | interested to see how this plays out.
        
               | jacobvosmaer wrote:
               | >not necessarily much safer than void*
               | 
               | You can cast void* to anything you want. With interface{}
               | you get a type check, either through an assertion or a
               | panic. That is a big difference in safety.
        
             | VirusNewbie wrote:
             | Probably a bunch of that code was needless boilerplate you
             | could have gotten away with not writing if you had
             | abstractions such as parametric polymorphism.
        
             | leshow wrote:
             | It's not as if it's a niche problem requiring a niche
             | solution though. The problem is "how do I write my own data
             | structures" and to the best of my knowledge Go's answer is:
             | copy-paste everything and edit for each concrete type, use
             | code gen, or pay runtime cost for interfaces. All of those
             | solutions seem more complex than just having a type
             | parameter.
        
               | jshen wrote:
               | They seem more complex compared to a type parameter when
               | you are only thinking about this narrow situation.
               | However, generics are not limited to this narrow
               | situation and will cause complexity far beyond what you
               | are imagining.
               | 
               | Having said that, I honestly don't know if generics are a
               | net positive or not. What I can say is that go is one of
               | the few languages where I can jump into an arbitrary go
               | code base and make sense of it relatively easily. Risking
               | that is a scary proposition for me.
        
               | garethrowlands wrote:
               | Just call it parameterisation, it's less scary then. The
               | unknown is always scary but having the ability to
               | parameterise - including types - is well traveled ground.
        
               | Fire-Dragon-DoL wrote:
               | This can be said for any programming language and any
               | community: there will always be bad code written by
               | someone.
               | 
               | Generic data structures are provided in many programming
               | languages and there are many people that are very
               | experienced in writing some of these, so being able to
               | reuse, it's precious.
               | 
               | In general the lack of generic price surfaces when you
               | write libraries, not applicative code. But libraries are
               | a big portion of a codebase.
        
               | jshen wrote:
               | I've been coding for decades. I've used all the fancy
               | functional languages, written production code at scale
               | with complex type systems, etc. my experience, they don't
               | add a lot of value compared to the costs. In my old age
               | I've grown to prefer go for it's simplicity. I hope we
               | don't lose it, and you all have the option of using the
               | myriad languages that already do what you are looking
               | for.
        
               | Fire-Dragon-DoL wrote:
               | I think you misunderstood my point (maybe): I totally
               | agree with you. I've been coding for many years and
               | coming from Ruby where you can do "the worst stuff you
               | can think off" (really bad stuff: monkey patching,
               | building DSL etc.), I came to Go exactly to get relief
               | from all of that. I don't trust people having their hands
               | on all that power.
               | 
               | Still in my short Go career, I worked on at least 4
               | libraries, one of those needed generics to gain a huge
               | performance boost, the other worked around the lack of
               | generics, but I still wish it had it (a special kind of
               | logger). In applicative code, the main issue with lacking
               | of generics is the lack of generic slices functions
               | (map/select). Initially I thought it would be fine, but
               | then I wrote a piece of code that was visibly involved in
               | copying data from one slice to another with some changes
               | and that "shadowed" the "central" part of the code behind
               | a bunch of loop codes. In those cases, to improve the
               | ability to easily scan through the code, I wish I had
               | some generic slice function to deal with it. I appreciate
               | doing loops, but sometimes they are verbose enough to
               | hide the interesting part of a piece of code. This is
               | especially visible in applicative code where usually
               | performance is not as important as much as the business
               | logic.
        
               | brundolf wrote:
               | Go has some "special" built in functions like len() that
               | work across different structures. What if instead of
               | adding generics they added more of those special
               | functions for working with slices as you describe? Would
               | that have solved your problem?
        
               | Fire-Dragon-DoL wrote:
               | Of course, but remember that `len` has constant return
               | type, while in case of slices you'd have a return type
               | that's different on the input slice
        
               | brundolf wrote:
               | I see. I guess I assumed that the category of special
               | "privileged functions" would have their powers extend to
               | cover stuff like that (I haven't used Go, I'm just going
               | off of what I've read)
               | 
               | I'm very intrigued by the no-generics idea, so I'm
               | prodding at what might've made it workable enough that
               | this reversal wouldn't be necessary :)
        
               | Fire-Dragon-DoL wrote:
               | All good!
               | 
               | Well in Go the assumption is that you jump to interface{}
               | (equivalent to Object in Java or void* in C) when you
               | start having these kind of problems, but there is a
               | performance penalty in doing that, which shouldn't be
               | there if generics are present (and makes the code
               | DRAMMATICALLY worse with all the casting)
        
               | leshow wrote:
               | I'm well aware when they are useful, I've been using them
               | in languages for the past 10 years. By the same token
               | though, leaving type parameters out of the language has
               | had far reaching implications outside of this "narrow"
               | situation (I'll put forth that implementing a data
               | structure isn't a narrow situation). Error handling and
               | the lack of sum types also seem particularly egregious
               | and are heavily influenced by the lack of generic types.
               | 
               | > Having said that, I honestly don't know if generics are
               | a net positive or not. What I can say is that go is one
               | of the few languages where I can jump into an arbitrary
               | go code base and make sense of it relatively easily.
               | Risking that is a scary proposition for me.
               | 
               | I don't see how type params would make this harder, I
               | daresay I can think of a lot of instances it's much
               | easier. The caveat is that you simply don't understand
               | them, in which case it's a good thing to learn as many
               | languages do have them.
               | 
               | In any case all these arguments are well trodden so I'm
               | probably wasting my breath re-hashing here.
        
               | jshen wrote:
               | I've been using them for the past 30 years and have come
               | to a different conclusion. You have plenty of languages
               | that do what you want. I hope go doesn't lose what made
               | it different
        
               | leshow wrote:
               | Oh sorry, you were saying lack of generics were the
               | reason you could make sense of code easily, implying that
               | if a language has generics you can't make sense of it.
               | That seems juxtaposed to having used them for decades. In
               | any case I can tell you're passionate about this so I
               | think we can just agree to disagree.
               | 
               | That said I don't think there's much "hope", from the
               | looks of things it is coming to Go.
        
               | jshen wrote:
               | I'm hoping that Go still keeps it's relative simplicity.
               | It's lack of inheritance gives me hope that generics
               | won't be as complicate as it is in other languages.
               | 
               | I understand generics well, I just find code bases that
               | use a lot of abstractions harder to read than Go.
        
               | takeda wrote:
               | You know? Original Java was a fairly simple language :)
               | Generics were added in 2004 in J2SE 5.0.
        
               | [deleted]
        
             | danellis wrote:
             | > Usually, if you are thinking about generics you are
             | reaching for abstraction when you don't need to be.
             | 
             | That's pretty laughable considering the language designers
             | included type-parameterized collections in the language.
             | Apparently they recognized the need for them; they just
             | didn't think you were smart enough to make your own. After
             | all, Go was explicitly designed for programmers who are, in
             | the words of its creator, "not capable of understanding a
             | brilliant language".
        
             | pjmlp wrote:
             | I also wrote hundreds of stuff from 1986 up to 1994, my
             | first experience with generics, on Turbo C++ for Windows
             | 3.1.
             | 
             | Doesn't mean many of us want to keep living on that world.
             | 
             | I advise reading books like "From Mathematics to Generic
             | Programming"
        
           | silisili wrote:
           | You don't write singly linked lists of arbitrary data :).
           | 
           | In my 20+ years of development, I've definitely realized
           | everyone's brains and approaches work differently.
        
             | deanCommie wrote:
             | You do if you want your language to have a reusable Linked
             | List data structure so that everyone doesn't have to re-
             | implement their own version of it for each content type.
        
               | silisili wrote:
               | There are languages that do this already though. Use
               | Python. Reusable everything, just wait for exceptions.
               | 
               | I've spent time in C, Python, Go, Js, and some lesser
               | known languages. I was really big into Python. Go seemed
               | restrictive at first, but was immensely more safe and
               | predictable.
        
               | SamReidHughes wrote:
               | Linked lists are the one data structure that you never
               | end up wanting a generic version of. They aren't really
               | used as containers. (Except badly.)
        
               | puddingforears wrote:
               | They're the easiest stack structure to implement. All
               | your operations are against the head of the list and you
               | either have a thing, don't have a thing, or add a thing.
               | I'd like to be able to maintain a stack of things whose
               | types I don't have to manually reify and erase. That's
               | not a tall order, and it's certainly not "complexity".
               | It's markedly weird that I can't have that same structure
               | and associated operations be usable regardless of the
               | thing I'm working with.
        
               | SamReidHughes wrote:
               | If you want a stack you'll just use a growable array (in
               | Go, a slice). A linked list is suboptimal.
               | 
               | Linked lists serve a real purpose in some situations
               | where you really do want O(1) behavior. One example is
               | when you are performing the operation while holding a
               | mutex. But it's never the sort of thing where the right
               | tool is a linked list generic container.
        
               | kroolik wrote:
               | I agree linked lists might be suboptimal for a stack
               | implementation, but for a different reason: data
               | locality.
               | 
               | You can have O(1) stack with both implementations. Slice-
               | based will be easier to follow, and will bust the cache
               | less often (less pointer jumps).
        
           | tptacek wrote:
           | You wouldn't. Everybody goes into Go thinking that's absurdly
           | confining. Some significant subset of Go programmers learn
           | that they instead find it liberating. Programming is
           | programming; you have an overwhelming number of degrees of
           | freedom no matter what language you work in. It sometimes
           | turns out that taking some of those degrees out of the
           | language makes it easier to focus them on your problem
           | domain.
        
             | [deleted]
        
             | int_19h wrote:
             | It's not like this is some kind of new or unfamiliar
             | experience. Many programmers had to deal with something
             | like that in Java or C#, back when they didn't have
             | generics. There's a reason why both got them eventually.
        
             | systemvoltage wrote:
             | This is one of the best definitions of 'minimalism' I've
             | seen.
        
             | reissbaker wrote:
             | While it's true that some find it liberating, a large
             | number don't -- personally, I've written a fair amount of
             | production Go code and found it unnecessarily verbose and
             | repetitive in ways that generics would've helped. I imagine
             | some of this is based on problem domain; if you're writing
             | a web application for example, maybe you don't really need
             | generics much. After all, how often do you need a function
             | that logs in a user to also log in... a book you're
             | selling? Not very often. And any advanced data structures
             | probably live in your database: how much do you really need
             | a B-tree in a webapp when you've already got one in MySQL?
             | 
             | That being said for a lot of other uses, you really _do_
             | want high quality data structures beyond  "array" and
             | "dictionary."
        
               | theshrike79 wrote:
               | You say "verbose and repetitive", I say "easy to read
               | without any surprises".
               | 
               | The verbose patterns (if err!= nil for example) make the
               | code predictable to read, you notice the code smell of
               | missing error handling really fast.
        
               | the_gipsy wrote:
               | In rust you have to swallow an error quite explicitly. In
               | go it's extremely easy to swallow one "err", by assigning
               | to some previous one which was already checked.
        
               | andy_ppp wrote:
               | Personally I find code with generics just as easy to read
               | as (largely duplicated) implementations for each type. I
               | might consider Golang again when this drops and there are
               | things to be like about how low level it is...
        
               | takeda wrote:
               | I think readability has multiple dimensions, and it
               | really depends what you are looking for.
               | 
               | For example here's a code in Go to look for a Prime:
               | func IsPrime(n int) bool {             if n < 0 {
               | n = -n             }             switch {
               | case n < 2:                     return false
               | default:                     for i := 2; i < n; i++ {
               | if n%i == 0 {                                     return
               | false                             }                     }
               | }             return true         }
               | 
               | It's readable as it is simple to understand what each
               | line does.
               | 
               | Here for example is a code that does the same thing in
               | Rust:                   fn is_prime(n: u64) -> bool {
               | match n {                 0...1 => false,
               | _ => !(2..n).any(|d| n % d == 0),             }         }
               | 
               | It's might seem more complex at first (what does match
               | do, what 0...1 means, !(2..n) what is any() doing. But if
               | you understand the language it actually this seem much
               | simpler and you can quickly look at it and know exactly
               | what it is doing. And because it is less verbose it is
               | easier to grasp the bigger code.
               | 
               | I also noticed that while individual functions in Go are
               | simple to understand and follow, you can still create
               | complex, hard to follow and understand programs in Go.
        
               | vips7L wrote:
               | Go is crazy verbose. Even Java can do it much more
               | simply:                   static boolean isPrime(int n) {
               | return switch (n) {                 case 0, 1 -> false,
               | default -> !IntStream.range(2, n).anyMatch(i -> n % i ==
               | 0)             }         }
        
               | bopbeepboop wrote:
               | You changed function signatures from int->bool to
               | uint->bool, which changes how long the functions are.
               | 
               | That seems unfair when comparing:
               | 
               | Removing negatives from the Go implementation removes 6
               | out of 16 lines, bring it from 3x Rust to 2x Rust in line
               | length.
        
               | takeda wrote:
               | I used code from: https://endler.dev/2017/go-vs-rust/
               | good point, I overlooked that.
               | 
               | Anyway in Go (ironically because of lack of generics) if
               | you use any numeric type other than int, int64, float64
               | you will be in the word of hurt. Rust doesn't have that
               | issue.
               | 
               | So in practice you will likely use int, and I suppose you
               | can add an assertion.
               | 
               | BTW: I only see that it would remove 3 lines though,
               | where are the other 3?
        
               | tptacek wrote:
               | I don't follow. I use unsigned ints in Go all the time.
               | I've never been in a world of hurt with them. Mandatory
               | explicit integer conversions (and the way Go consts work)
               | are something Go gets right.
        
               | takeda wrote:
               | Ok, so you like that. I myself really hated when I used
               | float32 and had to do this when I was doing calculations:
               | result = (float32)Max((float64)a, (float64)b)
               | 
               | I ended up switching the type to float64, and wonder why
               | they even offer float32 if it's practically unusable. I
               | had similar experience when I needed to use int8 or int16
               | etc.
               | 
               | An alternative was to make own version of Max/Min and
               | other math functions, but this is what generics would
               | solve.
        
               | tptacek wrote:
               | I'm not sure I follow, because Rust is also (thankfully)
               | fussy about integer types.
        
               | masklinn wrote:
               | I think what they mean is utility functions (e.g. min/max
               | here) tend to only be implemented for one type, so if
               | you're using an other you keep casting back and forth.
               | 
               | Rust is very fussy about types and some operations are
               | bound to a single one (e.g. stdlib sequences only index
               | with usize) but utility functions tend to either be
               | genetic or be mass-implemented using macros (or by hand
               | probably for f32::min and f64::min though I did not
               | check).
        
               | takeda wrote:
               | I don't have problem with being strong typed, I like that
               | as well. The problem is that the stdlib doesn't really
               | support other types and that's mostly due to lack of
               | generics, so using uncommon types becomes quite annoying.
        
               | masklinn wrote:
               | TBF the float Min/Max issue has nothing to do with
               | generics, there isn't a "floating-point" generic class,
               | and the entire reason why Go has an f64 Min/Max in the
               | first place is that floats are not fully ordered[0], so
               | you "can't" use regular comparisons (which you'd be told
               | to do for integers) and thus you could not have a generic
               | min/max relying on that even if there was one (e.g. in
               | Rust `f32` and `f64` are not `Ord`, which
               | `std::cmp::{min, max}` require, hence both `f32` and
               | `f64` having their own inherent min/max methods).
               | 
               | So what your issue comes down to is Go's designers
               | couldn't be arsed to duplicate the entire `math` package
               | to also work on `float32`. Some members of the community
               | did rise to the challenge[1] tho.
               | 
               | [0] well recent revisions of IEEE-754 have a total
               | ordering predicate but I wouldn't say that it's really
               | useful for such a situation as it positions NaNs on
               | "outside" of the numbers, so a negative NaN is smaller
               | than a negative number and a positive NaN larger than a
               | positive number
               | 
               | [1] https://github.com/chewxy/math32
        
               | takeda wrote:
               | I'm aware of it, in the example given I used float32.
               | Anyway Max/Min was just example I used other functions
               | from math as well.
               | 
               | Anyway my point was that with generics, they wouldn't
               | need to copy anything, the math package would work with
               | both float32 and float64 and many functions likely would
               | also work on all integers.
        
               | theshrike79 wrote:
               | The difference here is that I can hand off the first code
               | to any random freshly hired CS grad or cheapest
               | outsourced coder and they can grok the code quickly. This
               | is the advantage Go has to all other languages.
               | 
               | The Rust code needs maintenance coders of way higher
               | caliber, not something you'd usually find. It's super fun
               | for the top-tier developers who love to be expressive and
               | concise with their code, but all code is pushed down to
               | maintenance mode eventually when the hotshots move on to
               | the new shiny project.
               | 
               | Go has removed pretty much every footgun by sticking to
               | the basics. You have one way to do a loop, one way to do
               | comparisons etc. There are very few ways to hide non-
               | obvious functionality.
               | 
               | It _is_ possible to create complex programs, that are
               | hard to follow but that's a larger design problem. Not
               | something the language can force on developers.
        
               | anothernewdude wrote:
               | You're right that a templating language would reduce the
               | code and make it easier to read.
        
               | coryrc wrote:
               | Or use Option or Result, so your error handling is small
               | and forcibly correct.
        
               | tptacek wrote:
               | Error handling in Rust isn't always small or
               | straightforward. I miss both options and match
               | expressions when I switch back to Go from Rust, but
               | there's also tangles of or_else's and maps and the fact
               | that everyone uses third-party libraries to work out the
               | types for errors. There's tradeoffs everywhere you look.
        
               | int_19h wrote:
               | Zig is probably a better comparison for this:
               | 
               | https://ziglang.org/documentation/master/#Errors
        
               | dmitriid wrote:
               | > if you're writing a web application for example, maybe
               | you don't really need generics much
               | 
               | All our microservices return a { result: ... } or a {
               | result: ..., nextPageToken }
               | 
               | We would definitely benefit from generic SingleResult<T>
               | and PagedResult<T>.
               | 
               | Instead, you copy-paste the same definitions over, and
               | over, and over, and over again for every call.
        
               | jrockway wrote:
               | I think I see what you're doing. Right now, each result
               | type implements NextPager, which returns information
               | about how to fetch the next page. You client can
               | implement a utility like FetchNextPage:
               | type NextPager interface {             NextPage()
               | PageSpec         }         func (c *Client)
               | FetchNextPage(ctx context.Context, current NextPager)
               | (interface{}, error) {             ...         }
               | 
               | Then for each type of paged object, you write:
               | func (c *FooClient) FetchNextFoo(ctx context.Context,
               | current Foo) (Foo, error) {            next, err :=
               | c.client.FetchNextPage(ctx, current)            ...
               | if n, ok := next.(Foo); ok {                return n, nil
               | }            return Foo{}, fmt.Errorf("unexpected type:
               | got %T, want Foo", next)        }
               | 
               | That's annoying. But, this problem has come up before
               | with `sql`, which has rows.Next() and rows.Scan() to
               | iterate over arbitrary row types, and you could use that
               | as a model:                   pages := client.Query(...)
               | defer pages.Close()         for pages.Next() {
               | var foo Foo             if err := pages.Scan(&foo); err
               | != nil { ... }             // do something with the page
               | }
               | 
               | Generics would let you enforce the type of `foo` at
               | compile time, but it wouldn't save you many lines of
               | code. I think you still have to write (or generate) a
               | function like `func (c *Client) ListFoos(ctx
               | context.Context, req ListFooRequest) (Paged[Foo], error)
               | { ... }`. We hand-wave over that in the above example
               | with a "..." passed to query (potentially possible if you
               | retrive objects with a stringified query, like SQL or
               | GraphQL), but that sounds like the hard and tedious part.
               | 
               | Let me conclude with a recommendation for gRPC and gRPC-
               | gateway as a bridge to clients that don't want to speak
               | gRPC. Then you can just return a "stream Foo", and the
               | hard work is done for you. You call stream.Next() and get
               | a Foo object ;)
        
               | dmitriid wrote:
               | > Generics would let you enforce the type of `foo` at
               | compile time, but it wouldn't save you many lines of
               | code.
               | 
               | You literally showed that "for each type of paged object,
               | you write <multiple lines of entirely unnecessary code>".
               | 
               | Where with generics you just have a single generic
               | function.
               | 
               | > We hand-wave over that in the above example with
               | 
               | The problem is: there's no hand-waving in reality.
        
               | dmitriid wrote:
               | I'm traveling, so can't properly expand on what I said,
               | but without generics the choice was:
               | 
               | - repeat unnecessary bolierplate code for every single
               | return type
               | 
               | - skip types completely and use a function that accepts
               | interface{} as a parameter and assigns whatever to that
               | variable
               | 
               | Neither are really acceptable in my opinion. And both
               | will be greatly simplified and improved by generics.
        
               | tptacek wrote:
               | Sure, that's true, and it's fine. There are people who
               | find s-expressions both liberating and clarifying, and
               | others who get lost in a sea of parentheses. And there
               | are problems that are especially amenable to
               | s-expressions, or generics, or fine-grained control of
               | memory allocation, or interwoven code and markup, object
               | hierarchies, and those problems sort of "ask" for
               | particular languages. But for the most part, this stuff
               | is subjective.
        
               | jolux wrote:
               | There are certain things that just can't be done without
               | generics, though. Type safe higher order functions, type
               | safe custom collections, etc. Of course, perhaps these
               | are all just subjective to you, because you can still
               | write any program you need without them. But not having
               | this feature does constrain the set of type-safe programs
               | you can write quite a bit.
        
               | 4ad wrote:
               | You can absolutely write type-safe higher order functions
               | without generics. You can't write _generic_ higher order
               | functions, but that 's a tautology.
               | 
               | Also higher-order functions are a moot point. Higher-
               | order functions give you convenience, but no increase in
               | expressive power (defunctionalization is an
               | homomorphism).
               | 
               | Of course, generics give you a true increase in power.
        
               | [deleted]
        
               | tptacek wrote:
               | I feel like it pretty much always turns out that the
               | things you can't do without generics are, like, second-
               | order things. Higher order functions, type safe custom
               | collections, those are tools. What we care about mostly
               | is _what we actually build_ , and people build pretty
               | much everything in every language, generics or not.
        
               | jolux wrote:
               | It depends what you're building. If you're writing a
               | library to do those things, they may well be first order.
               | Certain extremely useful patterns like parser combinators
               | rely on them. And of course, the current answer is just
               | "do something else instead." But I don't really see why
               | this _has_ to be the answer. Surely the decision to leave
               | them out is just as subjective as a decision to add them.
        
               | int_19h wrote:
               | By the same token, functions in general are second-order
               | things - you can build things just fine with GOTO, and
               | plenty of real-world software was built like that back in
               | the day. But we don't do that anymore.
        
               | dmix wrote:
               | To add to your point, not using generics in Go is a
               | choice too, even if it's now an option.
               | 
               | But some people like offloading that to the language: not
               | having it in a language means you don't have to control
               | for it on your team/project contributors + some 3rd party
               | library.
               | 
               | I felt Go filled this minimalist category well. It's
               | always nice having a modern mainstream option doing so,
               | not just a niche one on the fringes (ala LISP), even if
               | I'm not personally a fan.
               | 
               | I guess it's hard to keep saying no.
        
               | yawaramin wrote:
               | Yeah, but programming is the business of building little
               | tools to help you build what you actually want to build,
               | over and over again. E.g., you might have some API calls
               | in your code and need to implement an error handler on
               | some of them. You could repeat the error handler code on
               | all of them, or you could extract it out to a generic
               | function and just use it as a wrapper for the others:
               | let call1 arg = ...         let call2 arg = ...
               | let error_handler call arg = ...              let call1 =
               | error_handler call1         let call2 = error_handler
               | call2
               | 
               | Python made this kind of technique famous, but languages
               | with generics can do it pretty well too.
        
               | pjmlp wrote:
               | Yeah, we should have kept using macro assemblers instead
               | of needless abstractions.
        
               | tptacek wrote:
               | If you believe that absolutely, the way you imply here,
               | then we're all just chumps for not working in Haskell.
        
               | anonymoushn wrote:
               | One example of a thing you want generics for is image
               | processing procedures that operate on many different
               | image formats with different color spaces. If you use the
               | built-in image libraries (which is perhaps already a
               | mistake), then you have an image that owns its channels,
               | and you pass it to some resizing method or whatever, and
               | then that resizing method's innermost loop chases
               | pointers to find out which kind of image it was *for
               | every pixel*. For performance reasons, you may not want
               | to chase pointers in your innermost loop. Without
               | generics, you need to copy and paste a bunch of code once
               | per color space.
        
             | dehrmann wrote:
             | > You wouldn't
             | 
             | As someone who hasn't used Go, what would I do, then? The
             | question about a generic data structure was very practical,
             | your response was philosophical, and I still need a linked
             | list.
        
               | tptacek wrote:
               | You would use a slice as your non-associative container,
               | and you would write a loop over it. You just wouldn't use
               | a linked list.
        
               | dehrmann wrote:
               | And honestly, 9 times out of 10, I'm better off
               | rebuilding the list because vectors have lower memory
               | overhead and the memory is contiguous. But that one
               | time... I've also been spoiled by Java's _very_ rich set
               | of collections.
        
               | [deleted]
        
               | josephg wrote:
               | Linked lists aren't the best example because they're
               | almost never the right tool. But in the last month alone
               | on a rust project I'm working on I've used:
               | 
               | - Option, Result, and other stuff from the standard
               | library.
               | 
               | - My own B-Tree implementation w/ domain specific
               | enhancements, in about 4 different contexts
               | 
               | - A heap based priority queue
               | 
               | - A custom 2 level vec, to support arbitrary insert &
               | delete without shuffling elements around. (This turned
               | out to be faster than my b-tree but less memory
               | efficient.)
               | 
               | - Several different custom iterators, and iterator
               | combinators. Eg, I have an iterator over some data which
               | gets computed on demand. I have an iterator which
               | consumes and run-length encodes each item in another
               | iterator. And so on.
               | 
               | All of this stuff has generic type parameters everywhere.
               | The b-tree is generic not just over the stored data, but
               | also over the way its index works. I can specialize it to
               | do a bunch of different tricks by just changing a type
               | parameter.
               | 
               | All of this code is fancy and hence difficult to read for
               | the uninitiated. And that isn't the Go way. But there's a
               | big, valuable middle ground here. I'm glad Go is adding
               | some options to let people lean a little bit into
               | cleverer code when it becomes appropriate for the problem
               | domain. Emulating generics with interface{} seems worse
               | than just adding generics into the language.
        
               | masklinn wrote:
               | And even if you assert that the use cases for generic
               | _structures_ are limited (which is debatable but why not)
               | there 's definitely something to be said for generic
               | _functions_ over existing generic types e.g. currently if
               | you want to build utility methods over slices or maps
               | (like... set operations because everybody uses maps but
               | maps don 't have set operations) you have to pick
               | between:
               | 
               | * manually instantiating (handrolling) every version,
               | possibly duplicating it if you don't realise somebody
               | else did
               | 
               | * same except using codegen, which is easier to maintain
               | but has more semantic overhead (now you need to add
               | codegen to the project and there's an extra build step to
               | consider)
               | 
               | * or manually type-erase and cast back, risking type
               | safety and most likely performances
               | 
               | A flagrant example from the stdlib is the `sort` package
               | with its weird and alien interface (and Interface),
               | inability to use key functions, and which can only work
               | in-place.
               | 
               | Talking about in-place but circling back to generic
               | structures / collections, a big use-case I expect to see
               | for generics would be type-safe (immutable) concurrent
               | collections e.g. HAMT, RRB, .... Current Go significantly
               | limits the ability to "share by communicating" (as well
               | as _safely_ "communicate by sharing") as there's no good
               | way to build and make any sort of high-quality concurrent
               | collection available, whether persistent or mutable.
        
               | [deleted]
        
             | coryrc wrote:
             | Yeah, that's why Kubernetes had to develop code generators.
             | So focused.
        
               | pjmlp wrote:
               | That made that to themselves, the original prototype was
               | in Java and changed to Go thanks to some recently joined
               | team members that were very munch into Go.
        
               | tptacek wrote:
               | I wouldn't know, I don't use K8s. But I did write a code-
               | generating ORM for a Go project and found it in a bunch
               | of ways superior to the ORMs I'd used in dynamic
               | languages, like ActiveRecord. And I've also worked with
               | heavily parameterized Rust crates that kept 20 tabs open
               | in my browser just trying to work my way through a couple
               | function calls.
               | 
               | Don't get me wrong, I'd take Rust generics over codegen 8
               | times out of 10. But that ORM worked well, and was the
               | only time I ever needed to write a code generator in Go.
        
               | takeda wrote:
               | Sorry but there's a bit of bias, every author of a
               | library thinks that their approach is better than of
               | their competing libraries.
               | 
               | If they didn't, they would just not create another
               | solution.
               | 
               | Having said that you might be right with ORM though. One
               | of great reasons why ORM might be superior on statically
               | typed language is that you can rely on the type system to
               | ensure you writing correct code (you also get benefit of
               | autocompletion, refactoring in IDE etc). The problem
               | though is that the type system including generics might
               | not be sufficient to express it. So code generation could
               | be still superior here.
               | 
               | The JOOQ (not exactly ORM though) generates java code,
               | even though Java has generics.
               | 
               | BTW: I personally think though that actual proper way to
               | handle this problem is to what JetBrains did. They
               | integrated DataGrip into their IDEs (I think it's
               | available in the paid version though) after you connect
               | IDE to the database, it starts detecting SQL statements
               | in the code and treat it the same as rest of the code
               | (i.e. auto completion, some refactoring (they still need
               | to improve that more) etc). It makes an ORM no longer
               | necessary for me. I think that's probably the way to
               | solve the impedance problem.
        
             | silisili wrote:
             | I could not have said it better myself, despite trying.
             | Thank you.
        
           | durbatuluk wrote:
           | You can do something similar to container package which has a
           | double impl.
        
         | buu700 wrote:
         | I personally think this will be a great thing for the quality
         | of the language (no typed higher-order functions is a massive
         | pain point as-is), but at the same time one could argue that
         | this is an equally massive bait-and-switch for all the
         | developers who prefer Go's original take on "simplicity".
        
           | pm90 wrote:
           | Go is still pretty "simple". They didn't introduce a while
           | loop. Adding generics would arguably "simplify" the language
           | even further since you would presumably throw away a lot of
           | duplicated code.
        
             | mseepgood wrote:
             | They can simplify code, but they don't simplify the
             | language.
        
               | masklinn wrote:
               | The langage which already had generics except special-
               | cased to builtins the langage authors really wanted to be
               | generic and they know better than the peons so they have
               | the intellectual capacity to make this determination?
        
               | mseepgood wrote:
               | you sound bitter
        
               | masklinn wrote:
               | I'm just believing what Rob Pike told me about his target
               | users for Go.
        
             | Zababa wrote:
             | > Go is still pretty "simple". They didn't introduce a
             | while loop.
             | 
             | What are you talking about? There is already a while loop,
             | it's just under a different name. I don't think reusing
             | keywords for other purposes is an example of simplicity.
        
         | aptenoforst wrote:
         | If anything generics will make go code simpler. No more copy
         | pasting everywhere and the possibility of making useful
         | collection methods like map, filter and reduce.
        
           | barsonme wrote:
           | More concise, yes. Simpler? Maybe[0].
           | 
           | And for the record, I'm mostly in favor of adding generics to
           | Go.
           | 
           | [0]: https://talks.golang.org/2015/simplicity-is-
           | complicated.slid...
        
             | sascha_sl wrote:
             | It also depends on your use case. Kubernetes and its pile
             | of code generators will be much much simpler.
        
         | moth-fuzz wrote:
         | I agree. I feel like generics make more sense in a language
         | like Rust or D or C++ (templates) where you need the
         | performance of compile-time constructs, and generics
         | specifically have that semantic. In Go, it doesn't make as much
         | sense to not simply use an interface for the same purpose since
         | the language is less bare-metal (or, rather, implementation-
         | specific) by design.
        
           | int_19h wrote:
           | It's not just about performance, or really not so much about
           | performance - e.g. when Java added generics, they didn't make
           | it any faster than it used to be when you had to use Object
           | everywhere.
           | 
           | It's about type safety - i.e. catching bugs earlier and more
           | reliably. Every time you have to write an explicit downcast,
           | you are throwing away the benefits of using a statically
           | typed language in the first place. Which is fine, but then
           | why stop halfway, and not just go full dynamic? It doesn't
           | really make sense to have strong typing for scalars but not
           | for collections.
        
       | awinter-py wrote:
       | those aren't generics they're from the canadian aboriginal
       | syllabic block
        
         | erik_seaberg wrote:
         | For anyone who doesn't get it,
         | https://www.reddit.com/r/rust/comments/5penft/parallelizing_...
         | was a pretty funny workaround.
        
       | pjmlp wrote:
       | Finally catching up modern times!
       | 
       | Welcome to 1976.
        
       | shp0ngle wrote:
       | Hey, instead of "return value, err", we can now write it as
       | generic Option!
       | 
       | Kidding kidding, please don't do it kids
        
       | throwawaygo wrote:
       | Sadly go is losing the spirit it was built with and alienating
       | the experience that it needs to regain that spirit. This has been
       | my top feedback every go survey is that it is being designed
       | democratically where it needs to be led by experience.
        
         | [deleted]
        
       | valenterry wrote:
       | Two thoughts:
       | 
       | 1.) In a "simple language" (e.g. without generics) each line of
       | code is easy to read/understand. But reading/understanding the
       | whole program or application is difficult. In "not-simple
       | languages" it's the other way around.
       | 
       | 2.) An important criteria to judge the future of a language is
       | how foresight the language authors have. I read that the go
       | authors said in the past that they were not ready to add generics
       | because they didn't know how to do so in a good way. True or not,
       | retrospectively adding generics is not a great indicator for good
       | language design to me. Even if the addition of generics is a net-
       | positive thing, I expect that Go will go in the direction of C++,
       | having a lot of accidental feature complexity in the language.
       | 
       | I think it's better to do it like Lisp and keep a simple (but
       | nonetheless flexible) core. Or do it like Haskell and design the
       | language to elegantly allow as much abstraction as possible,
       | moving carefully towards that goal. For these kind of languages,
       | you better have people who have years long experience in exactly
       | this: designing powerful programming languages. A developer can
       | be the best in their own field, but they are doomed to fail when
       | trying to build a future-proof, well designed programming
       | language on their first attempt. (btw, not relating to the Go
       | author's here)
       | 
       | An example where this didn't work is Angular - from the first
       | moment that I got in touch with it, I knew it was built by
       | amateurs. It's only a framework, but the difference to a
       | programming-language is minor in the case of these kind of all-
       | encompassing frameworks. It is not surprising to me at all that
       | the completely redesigned Angular later on.
        
       | 3np wrote:
       | Wow, it's happening! For others completely out of the loop on
       | that there was even an accepted proposal that is now being
       | implemented:
       | 
       | https://go.dev/blog/generics-proposal
        
         | dang wrote:
         | Some related past threads:
         | 
         |  _Golang generics proposal has been accepted_ -
         | https://news.ycombinator.com/item?id=26093778 - Feb 2021 (168
         | comments)
         | 
         |  _Go generics proposal moves to "likely accept"_ -
         | https://news.ycombinator.com/item?id=26018649 - Feb 2021 (92
         | comments)
         | 
         |  _A Proposal for Adding Generics to Go_ -
         | https://news.ycombinator.com/item?id=25750582 - Jan 2021 (270
         | comments)
         | 
         |  _The Next Step for Generics_ -
         | https://news.ycombinator.com/item?id=23543131 - June 2020 (664
         | comments)
         | 
         |  _Generics in Go with Ian Lance Taylor (2019)_ -
         | https://news.ycombinator.com/item?id=22361089 - Feb 2020 (98
         | comments)
         | 
         |  _Why Generics?_ -
         | https://news.ycombinator.com/item?id=20576845 - July 2019 (254
         | comments)
         | 
         |  _Go 's updated generic proposal (Contracts)_ -
         | https://news.ycombinator.com/item?id=20541079 - July 2019 (61
         | comments)
        
         | d33 wrote:
         | As an outsider planning to eventually learn Go, I have two
         | questions:
         | 
         | 1. what's "Go tip"?
         | 
         | 2. does this allow us to approximate when it could make it to
         | one of Go's stable releases? I guesstimate it's something that
         | would land not sooner than within a year, right?
        
           | 4ad wrote:
           | The "tip" is the head of the development branch.
           | 
           | The plan is to have them available as a preview feature in
           | the next stable release, which is scheduled in about 6 months
           | time.
        
         | omgitsabird wrote:
         | The full proposal is here:
         | 
         | https://go.googlesource.com/proposal/+/refs/heads/master/des...
        
       | Taek wrote:
       | Not excited about this feature, I guess we'll see how frequently
       | it shows up in unwanted places. Generics in C++ really damage the
       | readability of the code sometimes, maybe the go devs have found a
       | better way.
       | 
       | Very skeptical, but the go devs have given me plenty of pleasant
       | surprises before, maybe we get another one here.
        
         | jrockway wrote:
         | The key to readability is programming with readability in mind.
         | Sure, languages play some part in that, but 90% of it is the
         | programmer. Go is simple right now, and generics do complicate
         | it, but even with the simplicity that Go has, people already
         | make a giant mess of it. As soon as you get any advanced
         | feature, people will abuse it -- colossal generic functions
         | that take 5 interface{} arguments (but only ever operate on
         | strings), one-off interfaces that have 35 methods, calling out
         | to cgo just because they can, and giant tangles of goroutines,
         | mutexes, semaphores, and sync.Pools all mixed together into one
         | big ball of sadness. But, while everyone has the ability to
         | create such a disaster area, some opt out and use the tool
         | correctly -- making the advanced language features an asset
         | instead of a liability. I don't think generics will change
         | this; when used sparingly and at the right time for the right
         | reason, it will make the code easier to read.
         | 
         | I did a quick look through all my open source projects to see
         | where I have accepted or returned an interface{} in my own
         | APIs, which is a strong signal that I'm looking for generics,
         | or am using a library that wants generics.
         | 
         | One case is interacting with Kubernetes. I have two
         | applications where I set up a reflector like
         | `cache.NewReflector(lw, &v1.Node{}, store, resync)`, to keep a
         | cache up to date; the implementation of "store" takes
         | interface{} for all the arguments (Add, Delete, etc.), even
         | though it only ever operates on a v1.Node. Generics will let me
         | ensure at compile time that I only have to worry about v1.Node
         | objects. Right now, that's handled with runtime assertions in
         | the reflector itself, and in every implementation of the
         | cache.Store. Generics clean this up.
         | 
         | Another case that comes up is processing random JSON objects
         | from the Internet with no defined schema. Those end up as
         | map[string]interface{}, and that won't change.
         | 
         | The last case is unmarshaling functions. I see some (in a JWT
         | validation library) that are of the form `func
         | Unmarshal(string) interface{}`. I don't really know what's
         | going on there, and I don't know if generics will help.
         | (Similarly, for the common case of unmarshaling JSON, I'm not
         | sure generics can improve the `err := json.Unmarshal(bytes,
         | &result)` API. I will have to look into it.
         | 
         | That's about it.
        
           | baby wrote:
           | > The key to readability is programming with readability in
           | mind
           | 
           | Imo Golang buried that theory. I've read a lot of Golang code
           | and it's always been the clearest and most readable code I've
           | read.
        
           | Taek wrote:
           | The reason that people find Go to be so much more readable
           | than anything else is because there's often only one way to
           | do the thing you want. The entire language spec is like 2
           | pages long, and the standard library is relatively thin -
           | generally there are not cases of two libraries that can be
           | used to accomplish the same goal.
           | 
           | This has the general effect of making every piece of code
           | familiar, because every piece of code is forced to use the
           | same ideas to solve adjacent problems.
           | 
           | The foil to this is javascript, where you've got a bunch of
           | different ways to set up functions and promises and async and
           | threading and communications and error handling, etc.
           | Javascript is a very flexible and high level language, but
           | that also means everyone solves problems in their own unique
           | way.
        
         | 5e92cb50239222b wrote:
         | Even I know (not really being a heavy C++ user) that C++
         | doesn't have generics, it has templates, which is a much more
         | powerful concept that's often overused.
        
           | masklinn wrote:
           | > Even I know (not really being a heavy C++ user) that C++
           | doesn't have generics, it has templates
           | 
           | So... you know wrong?
           | 
           | Templates are a form of generics. What templates are not is
           | an instance of _parametric polymorphism_.
        
         | papaf wrote:
         | _Generics in C++ really damage the readability of the code
         | sometimes, maybe the go devs have found a better way._
         | 
         | The culture might help. I think generics in Java are not
         | overused -- partly because they are not so powerful and partly
         | because Java, similar to Go, did not have generics for a long
         | time.
        
           | randomdata wrote:
           | C++ also went a long time without generics, and even when
           | support started to appear it was a separate code generation
           | step, requiring even more time before we saw first-class
           | compiler support.
           | 
           | Powerful, though.
        
       ___________________________________________________________________
       (page generated 2021-08-21 23:02 UTC)