[HN Gopher] Golang generics proposal has been accepted
___________________________________________________________________
Golang generics proposal has been accepted
Author : komuW
Score : 215 points
Date : 2021-02-10 19:48 UTC (3 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| _spoonman wrote:
| Is generics akin to overloading functions?
| manu3000 wrote:
| no, overloading functions is called "ad hoc polymorphism",
| whereas generics is called "parametric polymorphism"
| lastofus wrote:
| Out of curiosity, what changed between now, and when proposals
| for generics came up in years past?
| wwarner wrote:
| The main difference between the accepted proposal and the
| original proposal is that the original proposal introduced
| contracts and the accepted proposal folds all that
| functionality into interfaces.
| [deleted]
| mappu wrote:
| _> Go was released on November 10, 2009. Less than 24 hours
| later we saw the first comment about generics._
|
| - https://blog.golang.org/why-generics
|
| But it's just taken that long to come up with a good design.
| Most of the work has been pushed forward by core team member
| Ian Lance Taylor who put forward the case in
| https://github.com/golang/proposal/blob/master/design/15292-...
|
| This abstract proposal has been updated to link to a summary of
| concrete proposals at the footer, ""presented for historic
| reference. All are flawed in various ways""
|
| Type functions (June 2010) -
| https://github.com/golang/proposal/blob/master/design/15292/...
|
| Generalized types (March 2011) -
| https://github.com/golang/proposal/blob/master/design/15292/...
|
| Generalized types (October 2013) -
| https://github.com/golang/proposal/blob/master/design/15292/...
|
| Type parameters (December 2013) -
| https://github.com/golang/proposal/blob/master/design/15292/...
|
| But it wasn't updated with implementation proposals after 2013,
| most notably
|
| Contracts (2019) -
| https://github.com/golang/proposal/blob/master/design/go2dra...
| hnlmorg wrote:
| This isn't a new proposal. Go's maintainers have always been
| clear that they weren't against generics _per se_ but we're
| against rushing into implementing something without giving
| sufficient time to consider the options.
|
| Personally I don't think their time spent considering has
| resulting in anything better than if they had rushed into a
| solution (I'm not a fan of this proposal). But that's just my
| personal opinion.
| meddlepal wrote:
| Yea basically they're implementing Java-lite generics. I'm
| not sure what they have been waiting for exactly...
| mseepgood wrote:
| Java generics do type erasure, this proposal does not. Java
| generics do not work on primitive types or with operators,
| this proposal does. Java generics require unbounded parser
| look-ahead by using <>, this proposal avoids it by using
| []. These are just from the top of my head, I'm pretty sure
| there are more differences.
| skybrian wrote:
| I'm not sure what you're comparing to, but there were
| previous proposals that were pretty different (and worse in
| my opinion), and there were changes along the way in the
| drafts that eventually turned into the accepted proposal.
| [deleted]
| [deleted]
| hnlmorg wrote:
| I really wish they went with angle brackets like everyone else
| does. I get the argument about not wanting to break existing
| parsers but this is a significant enough language change to
| warrant that.
| geodel wrote:
| So you know languages which use angle bracket and now wish
| every other language should follow that. This seems more stuck-
| up that Go team's alleged opinion on not implementing generics.
| hnlmorg wrote:
| Woooah steady in there with the conclusion jumping.
|
| The reason I prefer angle brackets is just because I think
| it's a little more readable. For me square brackets and
| parentheses look too similar in long function declarations.
| This might be a symptom of my dyslexia but the fact remains
| it's a real readability issue for me.
|
| I actually wouldn't have minded if they used another visually
| distinct character either. Like the << / >> characters that
| were also proposed (even though non-ascii characters have
| usability drawbacks when typing code).
| eweise wrote:
| Scala uses square brackets. Never liked the look of angle
| brackets
| kyrra wrote:
| It actually causes ambiguous syntax that isn't easy to solve.
| See:
| https://go.googlesource.com/proposal/+/refs/heads/master/des...
| a, b = w < x, y > (z)
|
| Is this code doing 2 boolean compares, or is it calling a
| function with "w" with types x and y?
| hnlmorg wrote:
| I know it's not a popular opinion, but one thing I love about
| Perl and wished more languages adopted was the way how
| variables and functions could be prefixed by a special
| character ('$' for scalars, '%' for hashes, '@' for arrays
| and '&' for functions, though the latter was optional). Perl
| had a lot of properties that made it look a lot like
| executable line noise but those prefixes did help with
| readability in a way that a lot of more readable languages
| lack.
|
| In the case of Go and the example you've given, if 'W' were a
| function then the code should read like this:
| a, b = w() < x, y > (z)
| blandflakes wrote:
| The parens look like "helping ambiguous syntax" rather than
| "should read like this" here - if z is an argument to w,
| there was already a set of parens signifying the function
| call.
| Jtsummers wrote:
| In the example, we can't tell if w is a generic function or
| not (by looking at this line of code). Remove the spaces,
| as would be more conventional: w<x,y>(z)
|
| Is this two expressions on one line or one expression with
| two type parameters? Possible groupings:
| (w<x,y>)(z) // w is a generic function (w<x),(y>(z))
| // two comparisons
| robocat wrote:
| Could they not make the space (or no space) part of the
| syntax after the <. gofmt means that white space could be
| made significant... which is the lesser evil: syntactic
| whitespace or inconsistent semantic meaning (compared to most
| other languages)?
|
| I detest how syntactically overloaded our few ASCII symbols
| are, and using square brackets for templates seems wrong.
|
| Edit: Even better, use gofmt to convert each ASCII symbol
| into several unique Unicode symbols depending on usage, to
| show the semantic meaning. So [] as array is represented
| differently from [] as the template operator.
|
| Edit 2: I suspect this one decision will prevent some
| developers from investigating golang and thus affecting
| uptake - choice of syntax matters.
| hnlmorg wrote:
| The << / >> characters (sorry on phone so can't post the
| actual Unicode characters) was proposed and, like yourself,
| the Go team decided it might put people off. But to be
| honest I actually would have been ok with it.
| midrus wrote:
| "We don't need generics"
|
| "We don't need exceptions"
|
| "We don't need ORMs"
| coldtea wrote:
| 2 out of 3 right ain't bad. We really don't need ORMs
| geodel wrote:
| However you do need a different language.
| zxcvbn4038 wrote:
| Nobody will have anything to complain about once go has generics,
| we'll never hear about Golang on Hacker News again! It'll just be
| the Rust people complaining. ;)
| erik_seaberg wrote:
| There's always error handling.
| dcolkitt wrote:
| IMO the biggest factors for the success of Go are 1) super-fast
| compile times, 2) easy to interpret compiler errors, and 3) dead
| simple shipment of high performance, native static binaries.
|
| I think Go has succeeded, despite, not because of the language
| itself. One very big limitation being the lack of generics or any
| sort of ability to leverage higher-order types. Sometimes making
| a small modification to a large codebase can require a huge
| footprint of lines modified, just because so much code winds up
| duplicated in slightly different contexts.
|
| That being said, I really hope that Go's core team understands
| the drivers of its popularity and doesn't compromise the
| operational side for the sake of language improvements. Although
| higher-typed languages have no trouble achieving good runtime
| performance, it seems like there's a fundamental tradeoff at
| compile time. Scala, Haskell, even Typescript have painful
| compile times. I don't know if there's any theoretical reason for
| it to hold, but more typing complexity inevitably leads to slow
| compile times.
|
| And as for the topic of clear error messages, the higher-typed
| languages are all atrocious at this. Even templates in C++ are
| notorious for puking near impossible to decipher errors. This is
| something I'm sure can be fixed with enough engineering effort,
| but it would probably take _a lot_ of effort to get there.
|
| In general, I bitch about the Go language all the time. But I
| think we should recognize that the simplicity of the language
| gives us developers a lot of peripheral really nice usability
| benefits.
| rurban wrote:
| > high performance
|
| I would not call 2x slower than C high performance. Decent
| performance, yes. But certainly not high.
|
| It has easy to use concurrency, so it waits less than typical C
| code. This might lead to some high perf claims. But it is not
| Zababa wrote:
| > Although higher-typed languages have no trouble achieving
| good runtime performance, it seems like there's a fundamental
| tradeoff at compile time. Scala, Haskell, even Typescript have
| painful compile times.
|
| OCaml has always been known for having really fast compile
| times, and could be described as a "higher-typed language" I
| think.
|
| > And as for the topic of clear error messages, the higher-
| typed languages are all atrocious at this.
|
| Elm and Rust have made good progress here and have some of the
| most readable and useful errors out here, especially for
| beginners.
| [deleted]
| patrickmcnamara wrote:
| 4) It's standard library is also big, modern and well
| documented.
| novok wrote:
| I think specific features make compile time very long. Nullable
| types + ADTs / sum types / 'enums' are not one of them, because
| they don't add exponentials to the compile time like type
| inference & operator overloading does for example.
|
| Also adding nullables after the fact isn't very hard, other
| languages such as dart & objective-c have done it. The
| migration path isn't that hard either, since it is a completely
| new syntax that doesn't have to be a breaking change, so
| migrations can be gradual. Out of all the features that the new
| higher typed languages give, I think nullables are probably the
| best one out of them, and one of the cheapest for all the
| others to adopt. And while your adding nullables, you might as
| well add sum types because that is how you implement it anyway.
| SloopJon wrote:
| > Even templates in C++ are notorious for puking near
| impossible to decipher errors.
|
| "Even"? I actually miss the macro-like power of templates when
| I'm using generics in Java and C#, but generating the longest
| possible error message using templates is practically an
| Olympic sport. I presume that SFINAE is partially to blame,
| because a lot of the output enumerates all the candidates that
| didn't match.
| bcrosby95 wrote:
| This is why I've always hated C++. Taking something like
| templates, and abusing the turing-completeness of it. If I
| wanted macros I would use a language that actually supports
| them so I wouldn't have to resort to byzantine hacks. Stuff
| like this is why lots of people would rather use C over C++.
| AnimalMuppet wrote:
| Doesn't C++ exactly support C macros? In what way is using
| C macros "better" than using the exact same macros in C++?
| zwieback wrote:
| I love-hate C++ templates because deep down they are just
| macros and you don't have to obsess about constraints like in
| Java and C#.
|
| To me it's pretty interesting how the three big static OO
| languages have implemented generics: super flexible
| permissive macros in C++ (with murderous error messages),
| type erasure in Java (gross) and actual generics in the
| runtime (C#). For everyday usage it doesn't matter much but I
| always like thinking about what's going on under the hood.
| otabdeveloper4 wrote:
| Nice to know.
|
| So what's the timeline for proper exceptions now?
| tick_tock_tick wrote:
| What does this mean for a timeline on when we can start using
| them?
| mseepgood wrote:
| In a stable release maybe 1.18 (Feb 2022) or 1.19 (Aug 2022).
| In a beta release maybe 1.18 beta1 (Dec 2021).
| smasher164 wrote:
| This is a significant milestone for Go, and I'm extremely happy
| for the community. I didn't imagine getting here when I first
| started using the language, and yet here we are.
|
| Special props to Ian Lance Taylor and Robert Griesemer for their
| continued revisions of drafts, and exemplary discussion with the
| community in implementing feedback.
| maurys wrote:
| I wonder if over time, Golang will pick up more type features
| like Java and other languages have.
|
| The general consensus seems to be that powerful type systems are
| very effective.
|
| Personally, the low footprint runtime and concurrency primitives
| are enough for me and I wouldn't mind the language becoming "less
| simple" if it helps the ecosystem.
|
| Once generics are implemented, I can imagine people requesting
| for the next "missing" thing.
| SeanLuke wrote:
| > I wonder if over time, Golang will pick up more type features
| like Java and other languages have.
|
| I hope it doesn't pick them up _like_ Java did.
|
| When Java was considering generics, there were two major
| proposals out there. Sun decided on easily the worst one: type
| erasure. Now we're stuck with it.
|
| When Java was considering closures, there were two major
| proposals out there that I recall [one being to get rid of
| Java's broken local variable closure semantics]. Sun (Oracle?
| forget) again picked the worst of the two proposals. Now we're
| stuck with a real monstrosity.
|
| Java has an amazing history of picking the wrong way to do
| things and permanently saddling developers with it.
| wtetzner wrote:
| > When Java was considering generics, there were two major
| proposals out there. Sun decided on easily the worst one:
| type erasure. Now we're stuck with it.
|
| Though using type erasure may have made the JVM a better
| target for other languages.
| hota_mazi wrote:
| Type erasure was the best of these options, and it's one of
| the main reasons why Java became even more successful than it
| already was, and also the main reason why there are so many
| languages created on top of the JVM (as opposed to .net,
| which supports reified generics, which complicates enormously
| writing languages on it, especially for interop reasons).
|
| More details: https://www.beust.com/weblog/erasure-vs-
| reification/
| mauricioc wrote:
| Since type erasure was mentioned, it's worth noting that
| Philip Wadler (of Haskell fame) was involved both in the
| design of Java generics [0] and of Go generics [1].
|
| (Perhaps I should clarify that I don't have a strong opinion
| on type erasure.)
|
| [0] https://homepages.inf.ed.ac.uk/wadler/gj/Documents/gj-
| oopsla... [1] https://arxiv.org/abs/2005.11710
| novok wrote:
| Golang is google's backup to java if oracle didn't let them
| have java anymore, with some additional design goals for large
| companies like fast build times, better memory usage and
| something jr engineers can pickup without much trouble.
|
| They both have garbage collection, they both perform about 3x
| slower than static C and they're both mostly used for network
| services, which is the same as Java at google.
| 015a wrote:
| I think I'm ok with this as well.
|
| The developers behind Go have a really strong culture of taking
| a ton of time to implement any major language changes; very
| reminiscent of Java and C++. Talk around Generics began, well,
| when the language was first created, but even more seriously
| like five years ago, and it'll probably be another year before
| it hits production.
|
| I love this. Language changes need to be thought through
| considerably, with all angles considered, and by going slow it
| gives major developers time to give feedback, prepare, and most
| critically not always feel like the code they write will go out
| of date in three months. By comparison, writing anything in,
| say, Rust (and JavaScript ~four years ago, its better nowadays)
| feels exhausting, because its a constant battle with changing
| culture and evolving best practices.
|
| My favorite feature of Go is its characteristic of not carbon-
| dating codebases. Go written a decade ago looks _almost_ the
| same as Go written today; Contexts would be the single major
| pseudo-language-level feature added in that interim which may
| give away newer code. Adding new features is still important,
| balance in all things etc, and code written after generics will
| give another epoch of carbon dating. Go strikes this balance in
| a way that should be a model for every other language.
| AnimalMuppet wrote:
| > Once generics are implemented, I can imagine people
| requesting for the next "missing" thing.
|
| Perhaps. But there is (currently) no other feature that people
| have been whining about nearly as much as they have been
| whining about generics. So I think it's going to be a while
| before another need is felt to the same degree.
| 2pEXgD0fZ5cF wrote:
| As someone who hasn't followed the discussion all this time, is
| there an up to date example of what the generics syntax will look
| like?
| 4ad wrote:
| https://go.googlesource.com/proposal/+/refs/heads/master/des...
| 2pEXgD0fZ5cF wrote:
| Thanks!
| gautamcgoel wrote:
| This will probably be downvoted, but I personally never felt a
| huge need for generics. C doesn't have them and is arguably the
| most successful language in history. Yes, they are convenient,
| but they also add a lot of complexity to the language and
| toolchain. I suspect that this proposal being accepted is largely
| due to the huge growth of the Go community - I bet the original
| team (in particular, I'm thinking of Rob Pike) are at best
| ambivalent about this proposal and were outvoted.
|
| Personally, the proposal I was most excited about was to make
| ints be arbitrary precision by default. As someone who does a lot
| of math, this would have made Go much easier for me to use.
| Sadly, this proposal was scrapped a while back.
| mseepgood wrote:
| > I'm thinking of Rob Pike
|
| I do not remember him being against generics. He is the one who
| contacted his former colleague Phil Wadler to help with the
| theoretical validation of the type parameters proposal. In his
| talk about the Go 2 draft specifications (back then the
| proposal was still based on contracts) he was positive that a
| good design can be found. (*)
| https://www.youtube.com/watch?v=RIvL2ONhFBI
| hota_mazi wrote:
| PHP was also hugely successful, success is not the criterion by
| which this kind of feature should be decided.
|
| The bottom line is that generics allows the production of
| safer, more robust, more evolvable, more documented, more
| performant, code.
|
| Along with static typing, generics are simply a feature that no
| language created recently should be without.
| baby wrote:
| and less readable, less auditable, less understandable, etc.
| hota_mazi wrote:
| These are all subjective aspects which often confuse
| unfamiliarity with obfuscation.
|
| I can read generic code in multiple languages even when I'm
| not fluent in these languages.
|
| Once you get used to generic code, it actually becomes
| easier to read and understand than code where everything is
| type cast or Object typed all over the place.
| erik_seaberg wrote:
| A successful language requires less effort to solve your
| problem. That's why we create them, and it's strange how
| languages keep becoming popular without nailing this.
| baby wrote:
| Agree with you on the generics, they make code harder to read
| and the biggest selling point of Golang is that it's easy to
| audit/read/understand.
|
| IMO Golang needed sum types and match statements, but it didn't
| need generics.
| Kranar wrote:
| C11 added _Generic as a way to write generic functions, for
| data structures people use the preprocessor to code-gen
| instantiations of generic code.
|
| Rob Pike has nothing against generics and never expressed
| criticism of them. His concern was always fairly practical;
| among the numerous forms of generics that exist among different
| languages, and the significant variation and rapid evolution of
| them, how can such a feature be safely added to the language?
| moocowtruck wrote:
| "I meant there are no plans for generics. That's not the same
| as saying we plan not to do generics. It just means we don't
| have a plan.
|
| The FAQ is still accurate.
|
| -rob"
|
| "The time has come to change Go, given what we have learned
| over the past decade of using it in production. -rob"
|
| the reason this proposal was accepted is because rob and others
| liked this plan and said over a decade of production taught
| them it is an important thing to have, in fact rob asked wadler
| and company to help get things right for go.. so i would say
| you'd bet wrong
| s-video wrote:
| >I bet the original team (in particular, I'm thinking of Rob
| Pike)
|
| Apparently he's nervous but can think of useful applications of
| generics:
| https://old.reddit.com/r/golang/comments/jditu9/what_do_gene...
|
| Robert Griesemer was a coauthor on the Featherweight Go paper
| so I'm assuming he supports it. I would assume Ken Thompson
| doesn't care for generics but I think he's retired so he
| wouldn't vote on it anyway.
| zajio1am wrote:
| > C doesn't have them and is arguably the most successful
| language in history.
|
| And many C programs just emulate them using crazy macros, that
| are harder to write and are less typesafe than proper generics.
| opnitro wrote:
| C may not have generic types, but much of the standard library
| does use generics, just through the unsafe mechanism of
| `void*`. Likewise, go already includes some generic code (the
| array type), it's just treated specially.
| zwieback wrote:
| For me the desire to use generics shows up once I've invested
| some time in making fancy types. When I work in C that point
| is never reached since problems are solved "the C way".
|
| Personally I'm a huge fan of generics but I can understand
| how the keepers of Go might be reluctant to go down the path
| of C++, Java and C#.
| f8o wrote:
| I think that C# has a successfull implementation because it
| isn't just about syntax sugar. The runtime knows it.
| Generics+structs allows many optimizations.
| zwieback wrote:
| So true and portable across languages.
| wahern wrote:
| The equivalent to a void pointer in Go is interface{}. But
| very little of the C standard library uses void pointers--
| basically only those interfaces dealing with untyped blocks
| of memory, such as malloc and free. IME, you see interface{}
| far more often in Go code than you see void pointers in C
| code. And C actually has bone fide generics capabilities with
| _Generic, it's just very simple and manual.
| Cyph0n wrote:
| void * is very useful as an opaque pointer type. For
| example, it's used all over the place in collection
| implementations and user-defined arguments (e.g.,
| callbacks, pthread_create).
|
| It might not be used much in the stdlib (which is
| relatively small!), but libraries and applications rely on
| void * heavily in my experience.
| wing-_-nuts wrote:
| go's empty interfaces reminded me too much of the bad old
| days when everyone passed around Objects to java methods. I
| hated it.
| CarelessExpert wrote:
| > C doesn't have them and is arguably the most successful
| language in history.
|
| I'm not sure "C didn't have it" is a good litmus test for
| determining the value of features... C is called a portable
| assembler for a reason.
|
| > Yes, they are convenient, but they also add a lot of
| complexity to the language and toolchain.
|
| Conversely, proponents of generics would argue that not having
| them creates complexity for software developers who have to
| come up with alternative design patterns where generics would
| be a better fit.
|
| > Personally, the proposal I was most excited about was to make
| ints be arbitrary precision by default.
|
| Why would you want that? C doesn't have it... ;)
| gautamcgoel wrote:
| Haha, touche. Your response is fair. My point was only that
| some people act like any successful language _must_ have
| generics, which is demonstrably false IMO. I am not opposed
| to innovation and ergonomics (hence, my support for arbitrary
| precision ints), but we should carefully weigh the pros and
| cons of every new proposal, especially if it increases the
| complexity of the language and toolchain. In my opinion, the
| benefits of generics are outweighed by the cost of their
| complexity.
| CarelessExpert wrote:
| First: I ninja-edited my comment after the fact with a
| thought that occurred to me after I posted, so apologies
| there.
|
| Anyway, yeah, no argument there at all.
|
| I'll be honest, as an outsider that's somewhat familiar
| with Pike's obsession with simplicity in Go, I'm actually a
| bit surprised this is getting in. It does seem like the
| kind of high-complexity feature that was deliberately
| excluded from the language as part of its overall design
| ethos.
|
| But it really comes down to a weighing of pros and cons.
| Generics have the potential (though definitely not the
| guarantee!) to trade off developer complexity for compiler
| and toolchain complexity, and the preference on that choice
| is a personal one.
| loopz wrote:
| Well, then you also know he just didn't see any good
| implementations of generics, yet. Let's hope this gets
| good!
| cies wrote:
| Well, we know now, contrary to what was said about generic-
| and-Go when Go came out: Go can apparently not do without
| generics.
|
| What I always found hard to swallow is that Go's build in
| functions sometimes did have generics. Just you as a
| library/application writer were not allowed to create APIs
| with generics yourself.
| Cyph0n wrote:
| Yep, seemed weird to me how (a form of) generics existed,
| but was exclusive to the stdlib/language.
|
| If generics were unnecessary, why did the stdlib/language
| need them? Couldn't they just have lived with, e.g.,
| make_map, make_slice, make_chan, etc?
| piinbinary wrote:
| And a separate copy of `append` for every possible type
| :)
| cies wrote:
| Exactly. It was IMHO pretty authoritarian to say "you
| dont need generics" and then use it yourself in the
| standard lib.
|
| But then Go is not a public place: it's private domain of
| Google.
|
| I decided long time ago I dont want to learn a private
| tool without being paid.
| matheusmoreira wrote:
| > I'm not sure "C didn't have it" is a good litmus test for
| determining the value of features
|
| It can be a good test.
|
| One reason why C is so ubiquitous is the simple binary
| interface. This makes it easy to reuse code since the
| libraries can be imported by every other language out there.
| C code is relatively simple and the compiled objects follow
| simple binary interfaces.
|
| Adding features to languages almost always increases the
| complexity of these binary interfaces. Eventually they become
| so complicated that nothing will ever interoperate with
| software written in these languages. The increased language
| complexity reduces the reusability of software produced in
| that language.
|
| C++ had this problem and Rust is following in its footsteps.
| Rust libraries are really only reused within the Rust
| ecosystem. Those that are meant to be universally reusable
| will no doubt offer a simple ABI that lacks all the benefits
| of the Rust language.
| samuell wrote:
| Very much excited that this is finally moving forward. Such sweet
| improvements this will allow for SciPipe and FlowBase when this
| nears completion [1,2].
|
| It will make it so much easier to enable typed port objects,
| which can still re-use all the handy functionality for connecting
| inports/outports, traversing the dataflow graph, etc etc.
|
| [1] https://scipipe.org
|
| [2] ihttps://flowbase.org
| cies wrote:
| This was to be expected. But I'm glad for Go.
|
| In some years a language that interops with Go comes out, where
| all the Go types have a ?-suffix indicating they are nullable.
| The language will be mostly null-safe. Also it will sport
| sumtypes and pattern matching/ destructuring in switch
| statements.
|
| It will be called: Gotlin.
| cies wrote:
| Of course I'm joking, but I think implicit nullability is the
| worst part of Go. A language designed in a era when this was
| widely known as the billion dollar mistake (prolly even more
| expensive).
|
| But this is not easily reversed. Not as easy as tagging
| generics onto the language. And the parallels with Java's
| maturing are just lovely. Also, we have seen what Kotlin is now
| doing for Java: a new language was needed to truly fix that one
| mistake (implicit nullability), introduced in the grandparent
| of Java (namely C), and the great old grand uncle of Go.
| baby wrote:
| Golang needed sum types (for options) and match statements
| (python got it after all...) way before it needed generics.
| CHANGE MY VIEW.
| sdfsfsf3kjdf wrote:
| How exactly are you going to implement a type safe option
| type without generics? You either have to use interface{},
| which is obviously not type safe, or write/generate an
| option type for every type contained within it. Sum types
| are a lot less useful if you don't have generics.
| alecbz wrote:
| It could have been built in to the language. Tons of
| builtin features (slices, maps, channels) are already
| "generic".
| cies wrote:
| Yes. But null-safety is absolute on the top (as it is soooo
| hard, maybe even impossible, to add later).
|
| Generics... Well, I just come from a Elm gig (knowing
| Haskell/C++/Java/Kotlin/Ruby) and I must say I was not too
| bothered with the lack of generics there.
| jasperry wrote:
| Wait, doesn't Elm have parametric polymorphism like other
| ML-family languages? That's just as powerful as most
| languages' generics, and with a lot fewer brackets.
| sdfsfsf3kjdf wrote:
| > Well, I just come from a Elm gig and I must say I was
| not too bothered with the lack of generics there.
|
| Elm has generics.
| cies wrote:
| Really? Why then there's List.map, Maybe.map, Array.map,
| and I have to select one of them? Is that not what
| generics would fix?
| sdfsfsf3kjdf wrote:
| > Is that not what generics would fix?
|
| No. That would be fixed by having something akin to
| typeclasses, traits or interfaces.
|
| Elm's List, Maybe and Array are all defined using a
| generic type parameter.
| floxy wrote:
| There is a terminology issue here, with "generic" being
| overloaded to mean different things. Parametric
| polymorphism is what Go is adding. You'd like to see
| something like ad hoc polymorphism in Elm, like type-
| classes in Haskell. But neither of those should be
| confused with the datatype generic programming.
|
| https://en.wikipedia.org/wiki/Parametric_polymorphism
|
| https://en.wikipedia.org/wiki/Ad_hoc_polymorphism
|
| https://wiki.haskell.org/Generics
| zeugmasyllepsis wrote:
| Sum and intersection types + pattern matching feels so
| natural in languages like F#, OCaml, Reason, and Elixir. I
| know they add a significant amount of complexity to the
| language, but the more I use them, the more I feel that the
| tradeoff lands in the goldilocks "just right" zone. I find
| myself missing them often.
| cies wrote:
| > feels so natural
|
| Yes. They are as important as records/structs a.k.a.
| product types.
|
| > F#, OCaml, Reason, and Elixir
|
| Haskell, Elm, PureScript, Kotlin, Idris, ...
|
| > I know they add a significant amount of complexity to
| the language
|
| Really? I dont think it can be so much more than generics
| :)
|
| Elm has 'm and the whole language is 5k lines of code.
| eeperson wrote:
| I think you want generics for many useful sum types (e.g.
| options) so you don't have to repeat your sum type
| definition everywhere it is used. Also, you can have
| options and matching without sum types (e.g. scala).
| merb wrote:
| btw. scala 3 might change that. there is a language
| feature which can be turned on to have explicit nulls,
| which will be in the form of union/sum types:
| https://dotty.epfl.ch/docs/reference/other-new-
| features/expl...
| coder543 wrote:
| > Of course I'm joking, but I think implicit nullability is
| the worst part of Go.
|
| Go doesn't have implicit nullability. You have to declare
| that something is a pointer for it to be nullable.
|
| There are a few kinds of pointers: "normal" pointers, slices,
| maps, function pointers, and interfaces. Any of those pointer
| types are nilable. Regular structs and primitives are not
| nilable. var x someStruct = nil //this will
| not compile var x int = nil //this also won't compile
| creata wrote:
| I don't like your definition of "implicit nullability".
| Following that logic, Java integers can't be null either,
| and C has no implicit nullability! In practice, when we say
| we don't want implicit nullability, we mean that we want
| nonnullable _everything_ , including pointers. After all,
| Tony Hoare called null _references_ his billion dollar
| mistake.
| coder543 wrote:
| That's not implicit nullability, in my opinion.
|
| I agree that non-nullable references are wonderful, and
| Go will probably have to grapple with that eventually. I
| just don't want people to get the wrong idea. Go has
| value types -- not everything is a reference that is
| implicitly nullable.
|
| C isn't implicitly nullable, you are correct.
| creata wrote:
| I feel like we're just using different definitions of
| implicit nullability, and by your definition, no language
| with value types is implicitly nullable, whereas by my
| definition, every language without nullable references is
| implicitly nullable. I think your definition is bad and
| uncommon, but that's not a very fruitful line of
| discussion.
| coder543 wrote:
| You're referring to how some languages have non-nullable
| references, which is fine. That's probably a better term
| to be using, since it is more clearly defined and less
| contentious in this discussion.
|
| I agree that Go should consider adopting non-nullable
| references.
| cies wrote:
| If I return a struct pointer in C, I can also return
| null. The return type does not communicate this to me:
| this is what I call implicit nullability.
|
| It is just a bad contract, as it is often misunderstood,
| and it allow for runtime errors that could easily have
| been caught at compile time.
| cies wrote:
| When i read Go code it is riddled with null guards. Any of
| those null guards may be removed, code compiles without
| additional warnings but now may blow up at runtime.
|
| Sorry, but to me that's a clear symptom of implicit
| nullability.
|
| Edit: clarification, to me it does not show in the type
| signature that something may return a null, also I do not
| have to unpack a possible null value (like with Maybe or
| Option).
| coder543 wrote:
| You can't check for nil on something that isn't nilable
| -- it's a compile error to do so in Go.
|
| Your definition of "implicit nullability" is suspect
| here.
|
| Go doesn't even implicitly de-reference things, which is
| what I think you're intending to say that it does. (EDIT:
| field access does cause a dereference, as was pointed out
| in a response to this comment. I still think of this as
| an explicit action when you're specifically operating on
| a pointer variable, but I'll concede this point here.)
|
| Your position on this is really confusing at the moment.
| Go handles nullability in an _extremely_ different way
| from Java.
|
| Edit for your edit:
|
| > clarification, to me it does not show in the type
| signature that something may return a null
|
| The best way to know something won't be null is to use
| value types where possible. Don't return nilable values
| unless you have a good reason. When you return nilable
| values, only return nil when the error value isn't nil.
| This is a common pattern in Go code. Why would you return
| nil if there wasn't an error? If there was an error, why
| would you care what else was returned, outside of some
| _very_ exceptional circumstances?
|
| > also I do not have to unpack a possible null value
| (like with Maybe or Option).
|
| I write Rust and Go professionally... I'm familiar with
| the pros and cons here, and I wish that Go would adopt
| Sum Types, but this has nothing to do with "implicit
| nullability", and in practice... it's really not a big
| deal. I've written huge amounts of Go code, and I just
| don't remember encountering nil exceptions in production
| except once in a blue moon -- and it is similarly common
| in Rust to hit an "expect" or "unwrap" that you thought
| was statically impossible to reach. Go has good editors
| (like GoLand) and linters (like golangci-lint) that make
| it easy to avoid most of the practical pitfalls.
| shric wrote:
| > Go doesn't even implicitly de-reference things
|
| Except when accessing a field via a pointer to struct.
|
| https://tour.golang.org/moretypes/4
| [deleted]
| cies wrote:
| > I wish that Go would adopt Sum Types
|
| And then make a Maybe sum type? But then it is too late
| as the std lib communicates with nils instead of Maybes
|
| > The best way to know something won't be null is to use
| value types where possible. Don't return nilable values
| unless you have a good reason.
|
| I'm not doing this, I'm using an API that does! I cannot
| choose what some code returns, all I can do is --sigh--
| add another null guard.
|
| If it is my discipline to add null guards or have runtime
| explosions I consider the nulls to be implicit.
|
| That you find as much runtime problems with unwrap/expect
| in Rust (which have a lot of red tape on them in API
| docs) as with "missing null guards" in Go, is great for
| you, but to me that does not make it a good design choice
| in Go.
| coder543 wrote:
| > If it is my discipline to add null guards or have
| runtime explosions I consider the nulls to be implicit.
|
| But they're still explicit nulls.
|
| You seem to be saying that only implicit nulls require
| null guards, but that's just not what that means (as far
| as I have learned).
|
| You seem to hate nullability as a concept, which is fine,
| but that's different from hating implicit nullability.
|
| > That you find as much runtime problems with
| unwrap/expect in Rust (which have a lot of red tape on
| them in API docs) as with "missing null guards" in Go, is
| great for you, but to me that does not make it a good
| design choice in Go.
|
| It's also a comment on how NPEs are just not a common
| hazard in Go compared to my past experiences with Java,
| especially when combined with good editors and linters.
| wtetzner wrote:
| > But they're still explicit nulls.
|
| Except that there may be other reasons to use pointers
| than just nullability. And in that case, there's no
| mechanism to specify whether or not the thing being
| pointed to is nullable.
|
| I think that's where the implicitness in question comes
| in.
| zzbzq wrote:
| Now that I've worked professionally in a whole bunch of
| languages that attempt to delete implicit nullability out of
| existence, I long for it's return. Option monads are a two
| billion dollar mistake.
|
| The fact is when you're working with any data coming from any
| other system, the data is or will become null, somehow, some
| way, and your program code which treats this as impossible is
| just literally wrong in a way that is complete jibberish.
| Additionally, programmers don't want to pass huge lists of
| parameters to every function, but instead bundle things into
| structs to be easily passed around, however this model makes
| it impossible to treat a value as Optional at an early part
| of the callstack and Non-optional later in the callstack
| after it's been checked and verified. So you either pass
| everything as a separate parameter, copy things into
| different structs all over the place, or just make the value
| Optional everywhere, deleting the usefulness of making
| Optionals.... Optional. Just let it be null everywhere, and
| if it's null somewhere it shouldn't be, the program throws an
| error--like it should, because there's an error.
|
| Actually, javascript is the only language that has it right.
| Not only can anything be null, anything can be undefined,
| (which isn't even remotely similar and anyone who doesn't
| understand why doesn't belong in the conversation,) AND
| values you don't know about can exist.
| cies wrote:
| > Actually, javascript is the only language that has it
| right. Not only can anything be null, anything can be
| undefined
|
| I think they are very similar in that there are now 2 nully
| things to guard for.
|
| Option types suck in Java as they were tagged on later.
| Maybe in Haskell, or even nicer, Maybe in Elm is were the
| party's at. It is build in at the center of the language.
| And getting a value (v) from a list by an index should give
| you a "Maybe v", as you could be out of bounds. That's the
| strong typing that basically keeps me safe when viciously
| attacking a code base I have not touched for some time (or
| is not written by me to begin with).
| mc10 wrote:
| I don't see how any of the points you made is a great
| defense of keeping nulls around.
|
| > The fact is when you're working with any data coming from
| any other system, the data is or will become null, somehow,
| some way, and your program code which treats this as
| impossible is just literally wrong in a way that is
| complete jibberish.
|
| Your program and the other program has to agree on some
| protocol. That can have optionality built into it if you
| expect them to not send certain fields. If that protocol is
| violated then either you made a mistake (protocol was not
| accurate) or they did (sent poorly formatted data); either
| way, you can handle the error without nulls.
|
| > however this model makes it impossible to treat a value
| as Optional at an early part of the callstack and Non-
| optional later in the callstack after it's been checked and
| verified.
|
| I think what's being described here could be easily encoded
| as variants/sum types, or you could have functions that
| give optional fields default values. Without a specific
| example it's hard to discuss what you're really trying to
| say.
| pjungwir wrote:
| I've been experimenting with Rust's Rocket webapp
| framework, and as much as I like it, I agree it's very
| annoying how a struct can't permit nulls in one context but
| not another. I wish there were an easy solution that didn't
| require near-identical struct definitions and excess
| copying memory from one place to another.
| wtetzner wrote:
| Seems like a good opportunity for a custom derive.
| sdfsfsf3kjdf wrote:
| In Rust you can solve this via derive or a macro.
| Typescript's conditional types and the associated utility
| types are a nice solution to this problem as well. You
| can do a ton with Partial, Required, Pick, Omit, Exclude
| etc.
| cactus2093 wrote:
| > copy things into different structs all over the place
|
| Sanitizing input is a very common pattern and I don't see
| why this option is such a deal breaker. And it would
| normally just be needed at the system boundary, rather than
| "all over the place".
|
| Or, you share types between different services using
| something like grpc or thrift, and then you really can
| trust that the values coming in are not going to be null.
|
| I definitely don't agree that settling for implicit null is
| the best option.
| novok wrote:
| > Just let it be null everywhere, and if it's null
| somewhere it shouldn't be, the program throws an error--
| like it should, because there's an error.
|
| Optionals everywhere makes that explicit, vs. something
| implicit that you can forget.
| beoh wrote:
| This is not an issue with Option at all. When you receive
| data from an external system, you should always parse it
| before making assumptions. By parsing I don't mean read
| property x as string, but make it a CustomerId for example,
| considering your constraints before accepting the value.
| acoard wrote:
| >Actually, javascript is the only language that has it
| right. Not only can anything be null, anything can be
| undefined, (which isn't even remotely similar and anyone
| who doesn't understand why doesn't belong in the
| conversation,) AND values you don't know about can exist.
|
| If you mean `unknown`, that's a TypeScript thing.[0]
|
| And personally I love working on a code-base and with
| coders that differentiate between null and unknown. But
| there's no denying it's a footgun and many get no value
| besides bugs from these two. It's kind of similar to how JS
| gets boolean comparisons weird, which is worked-around by
| convention
|
| [0] https://www.typescriptlang.org/docs/handbook/release-
| notes/t...
| pkulak wrote:
| > and your program code which treats this as impossible is
| just literally wrong
|
| That's fine though. The program that treats it as possible
| but fails to handle it in every possible spot is wrong too,
| but wrong in a completely unpredictable place, way and even
| number of times.
|
| It's freeing to start out assuming "title" can never be
| null. If it is, you get a quick failure at the very edge of
| your application where the data comes in. You make it
| nullable, and the compiler tells you all the places where
| you made the wrong assumption and now need a fix. Or even
| better yet, you give it a default value, even an empty
| string, and nothing more is required.
| p2detar wrote:
| Putting your rhetoric aside, you're mostly right. As someone
| that maintained an old Java project, a NPE was the most
| common type of issue that I had to deal with. The code was
| riddled with them and business logic often broke leaving me
| to deal with lots of support tickets.
|
| That being said, implicit nullability leads to mostly human
| type of errors and comes from our limitation to fit all the
| parts of a complex system in our brains. I'm curious if there
| are example where machines write code and use plenty of
| implicit nullability without that causing any NPE issues
| ever.
|
| Just a thought.
| cies wrote:
| Plenty of the example you request exist. Here two of m:
|
| Well Haskell compiles to binary, or Elm compiles to JS. The
| resulting binary/JS is basically machine written and does
| not throw any NPE's.
| Arnavion wrote:
| A more apt comparison is TypeScript to JavaScript, perhaps.
| Kotlin and Java interop at the bytecode level, but Golang
| doesn't have that. Gotlin would have to compile to Golang with
| the same shimming hairiness as TS downleveling to JS.
| AlphaSite wrote:
| Considering that go is only really used in a statically
| compiled context, thats not really necessary.
| cies wrote:
| Well spotted. Though typescript does not fix some of the
| biggest horrors of JS. Interop is really good as one would
| expect.
| mssundaram wrote:
| I'd say it depends on how you tune your tsconfig and
| linting. You can really crank all the knobs avoid nearly
| all of the JS pitfalls
| cies wrote:
| Agreed. But this is not very beginner friendly (sadly JS
| is more and more the first lang being taught), and is not
| an example of great design.
| pier25 wrote:
| For a brief moment I read Goblin
| lordofgibbons wrote:
| Will it requires a VM to run?
|
| Also, how fast will this language build large projects?
| cies wrote:
| It will be like Go: no VM. And have great interop with Go!
|
| > Also, how fast will this language build large projects?
|
| Slightly slower.
|
| I wonder what the implementation of generics will do to Go's
| otherwise stellar compile times. A code base heavily using
| generics can easily be double the compile time. Not sure how
| this will be sold, probably "but then simply do not use it!"
| erik_seaberg wrote:
| I'm made out of meat, the compiler is always going to be
| millions of times faster than that. Are generics actually
| slower than codegen plus parsing the same method body over
| and over with different types?
| cies wrote:
| > meat
|
| Flesh to me. (vegan) :)
| erik_seaberg wrote:
| Heh, it's a reference to https://www.mit.edu/people/dpoli
| car/writing/prose/text/think...
| [deleted]
| lalaithion wrote:
| Sad to see that we won't be getting type parameters on methods. I
| hope they fix the issues with it and can get that working in a
| future proposal.
| wmil wrote:
| I'm kind of sad that they didn't allow you to use inuktitut
| characters as a joke about this classic comment.
|
| https://www.reddit.com/r/rust/comments/5penft/parallelizing_...
| dang wrote:
| A few days ago: https://news.ycombinator.com/item?id=26018649
|
| A few weeks ago: https://news.ycombinator.com/item?id=25750582
| [deleted]
| baby wrote:
| I really really hope that this does not end up in people abusing
| generics in Golang code and making Golang code harder to read.
| The biggest argument of Golang in my opinion is that it is
| extremely easy to audit and read and understand at the moment.
| karmakaze wrote:
| When you get used to seeing it, the types mostly disappear from
| view until you look for it. I got to that level with Java, and
| Kotlin for the most part--never with Scala it always looked
| like line noise.
| tiborsaas wrote:
| Anything that can be abused in a language will be abused.
___________________________________________________________________
(page generated 2021-02-10 23:02 UTC)