[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)