News for hackers. Stuff that matters.
Re:Go 2 Draft Designs by rdsubhas on Tuesday August 28, 2018 @12:59PM (#17860499)
To be frank, I was for a long time on the camp that Generics is a much-needed feature of Go. Then, this post happened: https://news.ycombinator.com/item?id=17294548. The author made a proof-of-concept language "fo" on top of go with generics support. I was immediately thrilled. Credit to the author, it was a great effort.

But then, after seeing the examples, e.g. https://github.com/albrow/fo/tree/master/examples/, I could see the picture of what the current codebase would become after its introduced. Lots of abstract classes such as "Processor", "Context", "Box", "Request" and so on, with no real meaning.

Few months back, I tried to raise a PR to docker. It was a big codebase and I was new to Golang, but I was up and writing code in an hour. Compared to a half-as-useful Java codebase where I have to carry a dictionary first to learn 200 new english words for complicated abstractions and spend a month to get "assimilated", this was absolute bliss. But yes, inside the codebase, having to write a copy-pasted function to filter an array was definitely annoying. One cannot have both I guess?

I believe Golang has two different kinds of productivity. Productivity within the project goes up quite a lot with generics. And then, everyone tends to immediately treat every problem as "let's create a mini language to solve this problem". The second type of productivity - which is getting more and more important - is across projects and codebases. And that gets thrown out of the window with generics.

I don't know whether generics is a good idea anymore. If there was an option to undo my vote in the survey...

Re:Go 2 Draft Designs by jadbox on Tuesday August 28, 2018 @01:11PM (#17860614)
All I want is typesafe efficient higher order list operations like map, filter, reduce, flatmap, zip, takeUntil, etc. I don't care if Go puts them into the stdlib and only allows these operators to use special internal generics to operate. If Go had a robust higher order std library like this, I would stop asking for generics. Again, must be typesafe and zero overhead.
Re:Go 2 Draft Designs by bradfitz on Tuesday August 28, 2018 @01:24PM (#17860748)
One of the main motivations for adding generics is that we could then put typesafe algorithms and data structures in the standard library.
Re:Go 2 Draft Designs by quotemstr on Tuesday August 28, 2018 @01:27PM (#17860774)
And make the standard library unmagical? One of the things I've always disliked about Go is how stdlib provides magic facilities unavailable to user code.
Re:Go 2 Draft Designs by bradfitz on Tuesday August 28, 2018 @01:36PM (#17860881)
I agree, but there's not much, and it's usually for decent reasons:

* the "time" package hooks into the Go scheduler.

* the "reflect" package needs type information out of the runtime.

* the "net" package hooks into the Go scheduler a bit. But way less than it used to. I think you might even be able to do this all yourself outside of std nowadays.

What else?

Our rough plan going forward is to actually move a bunch of the stdlib elsewhere but ship copies/caches of tagged versions with Go releases. So maybe "encoding/json" is really an alias for "golang.org/std/encoding/json" and Go 1.13.0 ships with version 1.13.0 of golang.org/std/encoding/json. But if you need a fix, feature, or optimization sooner than 6 months when 1.14.0 comes out, you can update earlier.

Re:Go 2 Draft Designs by aleksi on Tuesday August 28, 2018 @01:44PM (#17860956)
My guess that quotemstr meant builtins: append, copy, range "protocol", etc.
Re:Go 2 Draft Designs by TheDong on Tuesday August 28, 2018 @02:08PM (#17861221)
There are many examples of things builtins can do which user-code can't:

1. The constructs like "x <- chan" and "x, ok <- chan" (and map indexing and so on) are only available to builtin types.

It's impossible to write a thing like "x, ok <- chan" where it either panics or doesn't depending on if the caller wanted two or one return values.

2. generic types, like 'map' and 'chan'.

3. 'len' can't be implemented for a user type, e.g. "len(myCustomWorkQueue)" doesn't work.

4. range working without going through weird hoops (like returning a channel and keeping a goroutine around to feed it)

5. Reserving large blocks of memory up front (e.g. as 'make' can do for slices and maps) in an efficient manner (e.g. make(myCustomWorkQueue, 0, 20) doesn't work)

Re:Go 2 Draft Designs by tptacek on Tuesday August 28, 2018 @02:40PM (#17861591)
You're talking about the language. He's talking about the standard library.
Re:Go 2 Draft Designs by quotemstr on Tuesday August 28, 2018 @02:58PM (#17861786)
We're both talking about both. The core of my complaint is that the language privileges parts of the standard library.
Re:Go 2 Draft Designs by TheDong on Tuesday August 28, 2018 @03:12PM (#17861917)
> privileges parts of the standard library

It really doesn't. Maps and channels are not part of the stdlib. They're part of the language, but not the library.

Similarly, range is part of the language, not the stdlib.

If the stdlib was privileged, "container/*" in it would be generic, but it's not.

Re:Go 2 Draft Designs by quotemstr on Tuesday August 28, 2018 @03:19PM (#17861982)
All right, but my point stands. Maps and channels should be part of stdlib, and they should rely on primitives available to user code too.
Re:Go 2 Draft Designs by tptacek on Tuesday August 28, 2018 @03:31PM (#17862092)
Maps and channels are not part of the standard library. How you know that is, you can replace the entire standard library, using none of it, and still be programming in Go with maps and channels.
Re:Go 2 Draft Designs by coldtea on Wednesday August 29, 2018 @07:24AM (#17867351)
Parent wrote "should be" not "are".
Re:Go 2 Draft Designs by thefounder on Tuesday August 28, 2018 @05:11PM (#17862917)
Such primitives would bring a lot of complexity which is something Go tried to avoid.

Consider that make, map, chan etc are just language features/specs just like int64, string, func, main etc

Re:Go 2 Draft Designs by quotemstr on Tuesday August 28, 2018 @07:50PM (#17863964)
Why should string be fundamental?
Re:Go 2 Draft Designs by tptacek on Tuesday August 28, 2018 @09:03PM (#17864341)
Nobody said it "should" be. It simply is, in Go, the language we're discussing. If you nerdsnipe an HN thread with an argument that there's no difference between a language, its runtime, and its standard library, people are going to pile on to point out that's not true.
Re:Go 2 Draft Designs by sagichmal on Tuesday August 28, 2018 @05:51PM (#17863249)
Could, sure. Should? I think you are asserting facts that are not in evidence.
Re:Go 2 Draft Designs by uryga on Wednesday August 29, 2018 @11:50AM (#17869148)
I'm a bit confused, and I'd like to understand your position better. I can see why arrays, structs/tuples, or [tagged] unions are usually primitives – they sort of express different fundamental layouts of data in memory, so they need support from the runtime/compiler. In the case of Go, channels also make sense as a primitive – as I understand it, `select` requires scheduler support.

But higher level data structures like lists, sets, maps etc. are all implemented using those primitives under the hood. So, especially in a "systems language", I would sort of expect them to just be libraries in the stdlib, not language features[1]. But if you think otherwise (or see a gap in my reasoning) I'd love to hear why!

[1] Except maybe some syntactic sugar for list/dict/set literals.

Re:Go 2 Draft Designs by sagichmal on Wednesday August 29, 2018 @04:29PM (#17871677)
"Should" implies some normative assignment of value.

> But higher level data structures like lists, sets, maps etc. are all implemented using those primitives under the hood. So, especially in a "systems language", I would sort of expect them to just be libraries in the stdlib, not language features[1].

Maybe! But if those higher order structures are closer to language features than libraries -- and, specifically to this conversation, if they leverage parts of the runtime that aren't available to mere mortals -- is it a strictly worse outcome? I don't know. Some evidence might suggest yes. But I think it's at best arguable.

Re:Go 2 Draft Designs by uryga on Thursday August 30, 2018 @08:31AM (#17876125)
I think I understand, thanks for explaining.
Re:Go 2 Draft Designs by TheDong on Wednesday August 29, 2018 @12:47PM (#17869691)
> But higher level data structures like lists, sets, maps etc. are all implemented using those primitives under the hood

In Go you don't have generics as a primitive with which to build those things.

As a result, you don't have the building blocks for anyone to build a usable data structure unless it's baked into the core of the language.

Re:Go 2 Draft Designs by uryga on Wednesday August 29, 2018 @01:11PM (#17869901)
I'm aware of that, and I read the generics proposal linked. I commented here because I wanted to respond to this:

> Should [be just libraries]? I think you are asserting facts that are not in evidence.

I tried to describe why I feel that go's collections should be libraries and not builtins, and hopefully understand why GP seemed like they were questioning that idea.

Re:Go 2 Draft Designs by icholy on Tuesday August 28, 2018 @01:35PM (#17860867)
What's magical about the stdlib?
Re:Go 2 Draft Designs by grey-area on Tuesday August 28, 2018 @02:08PM (#17861231)
Maybe they meant the language, which has some generic functions like append or delete - instead of those functions being attached to a data type or accepting any type, they only act on built-in types. I doubt any of that would change though given the stated goal of remaining compatible in most cases.
Re:Go 2 Draft Designs by SamWhited on Wednesday August 29, 2018 @11:17AM (#17868865)
There are a handful of packages (time and some stuff in os for example) that are tied into the runtime and can't be rewritten outside the standard library. It's not a huge amount, and some of it can probably be fixed in the future.
Re:Go 2 Draft Designs by tejasmanohar on Tuesday August 28, 2018 @04:40PM (#17862655)
What if generics were just implemented internally in Go? IMO, there are good use cases, like generic numbers (int32, int64, etc.), list processing, etc. There's already precedence for this with map[A]B, make(), etc.
Re:Go 2 Draft Designs by sdegutis on Tuesday August 28, 2018 @01:32PM (#17860826)
What changed? Why is the Go team finally considering this now, when it has been requested for these exact reasons by many credible developers since Go's beginning?

EDIT: Yes, something has changed. They always said "no, but maybe later" and now it's "ok how about now". That is a big change and I am just asking what's the reason for it.

Re:Go 2 Draft Designs by ianlancetaylor on Tuesday August 28, 2018 @02:41PM (#17861592)
A year ago we said it was time to move toward Go 2: https://blog.golang.org/toward-go2 . This is another step in that direction.
Re:Go 2 Draft Designs by sdegutis on Tuesday August 28, 2018 @06:50PM (#17863627)
Then I'm a year late in asking why the Go team is now deciding to say yes to something they said no to for over half a decade.
Re:Go 2 Draft Designs by ianlancetaylor on Tuesday August 28, 2018 @07:10PM (#17863733)
The blog post explains that.
Re:Go 2 Draft Designs by m_sahaf on Tuesday August 28, 2018 @01:34PM (#17860851)
Nothing changed. It wasn't off the table to begin with. See: https://golang.org/doc/faq#generics
Re:Go 2 Draft Designs by coldtea on Tuesday August 28, 2018 @03:02PM (#17861820)
The question of the parent boils down to "what put it on the menu".

So, yeah, it was always "on the table" in some hazy, we'll see later, way, but not like that.

Re:Go 2 Draft Designs by sagichmal on Tuesday August 28, 2018 @05:53PM (#17863261)
I think a good faith reading of the circumstance would lead one to conclude that the passage of time, and other, higher-priority and lower-cost-of-implementation issues being addressed, have put these issues on the menu.
Re:Go 2 Draft Designs by BurningCycles on Tuesday August 28, 2018 @04:17PM (#17862478)
Likely because they have now figured out implementations of these features which they feel work well with the rest of the language design.
Re:Go 2 Draft Designs by cridenour on Tuesday August 28, 2018 @02:21PM (#17861375)
Because now is later than when they said later?
Re:Go 2 Draft Designs by mikekchar on Wednesday August 29, 2018 @12:07AM (#17865527)
The reason for saying "no, but maybe later" originally was that it was always a desired piece of functionality. I believe the word "inevitable" was even tossed around. The problem was that they didn't like the existing implementations of generics in other languages and also didn't know how they would improve it. I haven't had time to look at the details, so I'm not sure what they actually did, but I think they basically came up with a strategy that they are mostly happy with.

You might ask, why not pick a solution earlier and then improve it over time? However with a popular language it's not that easy. People are writing lots of code. If you start early, you can paint yourself in a corner and end up with a system that you really can't improve very much because it introduces incompatible changes. Note the extremely painful (and drawn out!) incompatible changes with Perl 6 and Python 3. If you make the wrong choice early, you might still take over a decade to find an opportunity to replace it. And since the state of the art in language design moves very slowly, it took a long time before they could see something that they felt they wouldn't regret choosing.

Re:Go 2 Draft Designs by mikekchar on Wednesday August 29, 2018 @02:12AM (#17866055)
I highly recommend reading https://go.googlesource.com/proposal/+/master/design/go2draf...

This is part of the material linked to from this thread. It answers all your questions. You will see that some of the people who are directly replying to you are very much involved in this effort.

Edit: I tried editing the previous message but HN actually automatically made a reply instead....

Re:Go 2 Draft Designs by derefr on Tuesday August 28, 2018 @02:50PM (#17861687)
Adding generics is a major change (e.g. it would restructure the stdlib), and so it would only belong in a major-version bump of the language.
Re:Go 2 Draft Designs by kibwen on Tuesday August 28, 2018 @03:59PM (#17862335)
Though the authors have clarified that the "2" in "Go 2" is just for marketing purposes, and that the actual release would still be "Go 1.x", and shouldn't break any existing code (so it won't restructure the stdlib in any major way, unless they want to do a huge mass-deprecation).
Re:Go 2 Draft Designs by sdegutis on Tuesday August 28, 2018 @04:15PM (#17862454)
So Go is following the exact same path as Java.
Re:Go 2 Draft Designs by qznc on Tuesday August 28, 2018 @05:40PM (#17863142)
Inevitably.

Also inevitably, Java will get value types (structs) at some point.

Just like with Go Generics, people will complain the feature is bolted on. After some time it is just one of the many quirks of a complex language.

I think it was Stroustrup who said: there are two kinds of programming languages, the ones people hate and the ones nobody uses.

Re:Go 2 Draft Designs by pjmlp on Tuesday August 28, 2018 @05:42PM (#17863163)
And Java had quite a few good examples to take on like Modula-3 and Eiffel, but alas they wanted something for average Joe, kind of sounds familiar.
Re:Go 2 Draft Designs by sdegutis on Tuesday August 28, 2018 @05:44PM (#17863179)
The difference is that Go could have learned from Java.
Re:Go 2 Draft Designs by marcus_holmes on Wednesday August 29, 2018 @05:42AM (#17866970)
I think because it would break backward compatability in v1, and not doing that was the Most Important Thing in all 1.xx releases.

v2 is allowed to Break Stuff. So obviously they're going to consider the thing that people have shouted for most in Go... generics and error handling (and package management but they found a way of doing that earlier).

Re:Go 2 Draft Designs by bsder on Tuesday August 28, 2018 @02:54PM (#17861735)
> What changed? Why is the Go team finally considering this now, when it has been requested for these exact reasons by many credible developers since Go's beginning?

Simply, Go has probably accumulated all the developers it is going to accumulate without something drastically changing.

At this point, I can't think of any programmers around me who now want to learn Go.

Re:Go 2 Draft Designs by krylon on Tuesday August 28, 2018 @02:33PM (#17861507)
I basically agree. I still think, while we're at it, making Generics a general feature of the language would probably be easier than adding all kinds of special cases.

But yeah, if Go just added a generic map/filter mechanism (Python's list comprehensions (in turn inherited from Haskell) look very nice), that would cover about %75 of the use cases I want Generics for. Add a generic mechanism to use the range operator with user-defined types, and we're at about 95%.

Re:Go 2 Draft Designs by thiht on Wednesday August 29, 2018 @08:23AM (#17867647)
> Python's list comprehensions (in turn inherited from Haskell) look very nice

Do they? I find them hard to read and hard to chain. I tend to prefer basic map, filter, reduce methods

Re:Go 2 Draft Designs by krylon on Friday August 31, 2018 @05:48PM (#17888800)
Mmmh, that is a good point. I never used nested list comprehensions, to be honest, and I have not used Python in a couple of years. For non-nested cases, they are very nice, though.

OTOH, I never used nested map/remove-if constructs in Lisp, because that, too, can get rather annoying to read.

Re:Go 2 Draft Designs by AndyMcConachie on Tuesday August 28, 2018 @03:21PM (#17862001)
I agree with this sentiment completely. Of course, if the only way to get these wonderful list operations is generics, then I guess I want generics, too.
Re:Go 2 Draft Designs by nemo1618 on Tuesday August 28, 2018 @07:07PM (#17863721)
You might be interested in my project: https://github.com/lukechampine/ply

The idea is that when people say "generics", they usually just mean map/filter/reduce. So ply just bakes those into the language directly instead of adding new generic programming facilities.

Re:Go 2 Draft Designs by ori_b on Tuesday August 28, 2018 @02:19PM (#17861350)
Those are the things that I don't want to see in Go, honestly.
Re:Go 2 Draft Designs by pwm on Tuesday August 28, 2018 @02:27PM (#17861435)
I'm curious: why not?
Re:Go 2 Draft Designs by ori_b on Tuesday August 28, 2018 @05:09PM (#17862906)
Generally, chaining things in the style that encourages that makes it harder to debug the code, harder to step through it in my head or on paper, and harder to compile to performant code. I'd rather see loops.
Re:Go 2 Draft Designs by bschwindHN on Tuesday August 28, 2018 @10:17PM (#17864885)
On the other hand, you're less likely to need to debug those things because they've been implemented once, correctly. A manually-written filter, map, etc. will pretty much always have a higher probability of containing a bug. And in languages that have these features, I've never found it difficult to debug. What issues have you had in the past?
Re:Go 2 Draft Designs by ori_b on Wednesday August 29, 2018 @12:50AM (#17865732)
I've almost never had issues with manually written filters/maps -- at least, not with the iteration itself. On the other hand, having to untangle stack traces of closures of closures that have been passed through closures does slow me down when the function that's being mapped is buggy.
Re:Go 2 Draft Designs by bschwindHN on Wednesday August 29, 2018 @03:52AM (#17866494)
I guess I've never run into issues where a map or filter slowed me down for debugging, most languages will pretty easily show you where the error occurred. And if you're `map`ping and `filter`ing with pure functions, debugging is pretty simple because you just need the input that went into the buggy function. A good compiler will also optimize the closures into something you'd write by hand in Go. Overall I'm glad to see Go get these nice tools for more easily working with collections.
Re:Go 2 Draft Designs by ori_b on Wednesday August 29, 2018 @04:36AM (#17866702)
I've just never run into places where that style improved readability, performance, or debuggability. Outside of the Haskell world, I've usually found myself preferring loops for ease of following the code.
Re:Go 2 Draft Designs by pwm on Wednesday August 29, 2018 @04:46AM (#17866752)
Thanks for your answer. I find it very interesting how different people come to different conclusions about these basic approaches to writing programs. Imho, as always, there's no one true answer and understanding where everyone comes from is very important in understanding this divergence of thought.

In my work I don't think I could live without these higher level abstractions anymore. It enables me to write clear and concise code that helps me keeping accidental complexity under control so that I can focus on the essence of what I'm trying to codify. Performance on the other hand is not a primary concern to me, given it stays above some acceptable threshold.

I appreciate how different tasks would require different approaches. I'm interested in which direction go goes (no pun intended).

Re:Go 2 Draft Designs by platinumrad on Tuesday August 28, 2018 @02:23PM (#17861389)
At that point why not just add generics...
Re:Go 2 Draft Designs by nine_k on Tuesday August 28, 2018 @03:11PM (#17861904)
Lisp tends to build abstractions, too, and it also does that via macros, which are even harder to mentally parse unless you have a habit.

I'd say that to attain simplicity and clarity, you have to limit the use of abstraction. OTOH there's no way to avoid abstraction at all; programming is all about abstraction. If the means of abstraction are not powerful enough, copy-paste programming and boilerplate proliferate, making code less maintainable and harder to understand.

Re:Go 2 Draft Designs by platinumrad on Tuesday August 28, 2018 @03:18PM (#17861976)
In my opinion, implementing these higher order functions with the help of one powerful abstraction (generics) is much simpler than having to deal with a bunch of special cased weaker abstractions (magic map, magic filter, magic reduce, magic...).
Re:Go 2 Draft Designs by gekkonier on Tuesday August 28, 2018 @02:21PM (#17861373)
So you want a Lisp with other syntax, right?
Re:Go 2 Draft Designs by codr4 on Tuesday August 28, 2018 @03:18PM (#17861972)
That's about right. And gradual types, multi methods, generics and tight integration with C++: [0].

Dylan was too long winded for my taste, as are most modern attempts.

[0] https://github.com/codr4life/snabl

Re:Go 2 Draft Designs by coldtea on Tuesday August 28, 2018 @03:03PM (#17861833)
You say it like it's a bad thing.
Re:Go 2 Draft Designs by gekkonier on Tuesday August 28, 2018 @03:25PM (#17862039)
I was just curious, because those functionionality wished is in nearly every list processor, no mather what syntax used. And if not you macro that away, right?
Re:Go 2 Draft Designs by grey-area on Tuesday August 28, 2018 @01:33PM (#17860837)
Some abstractions have stood the test of time - map, reduce, sort, those are worth having and various other collection types would be nice to see.

I agree the introduction of generics is a big worry not because of what good programmers will do with it, but because of what people more enamoured with pretty abstractions than code that does work will do with it. I don’t particularly want to live inside someone else’s creation for weeks just to understand it. The existing culture of no nonsense and minimal abstraction should help police that though.

I’m not that keen on the syntax of contracts either, but we’ll see what comes out at the end, that’s not so important - the idea of contracts looks like a good one in theory at least, but it feels like they could have used interfaces instead somehow (I’m probably missing something there).

The errors proposal is interesting as it looks like try/catch at first glance but importantly doesn’t leak that error across function/lib boundaries as exceptions do, so it’s a natural extension of the existing approach.

Re:Go 2 Draft Designs by lazyjones on Tuesday August 28, 2018 @04:45PM (#17862703)
> I’m not that keen on the syntax of contracts either, but we’ll see what comes out at the end, that’s not so important - the idea of contracts looks like a good one in theory at least, but it feels like they could have used interfaces instead somehow

I'm not sure I understand the need for contracts really. If a function with type argument is compiled, the caller should use specific types to call it, so the compiler can determine whether said type has the required methods used in the generic function. Therefore the compiler knows everything it needs to fail with a compile-time error without any extra ugly "contract" syntax. What am I missing? Are some types only resolved at runtime?

Re:Go 2 Draft Designs by summerlight on Tuesday August 28, 2018 @05:08PM (#17862898)
That's exactly what C++ is doing for their template. The problem here is that if you want to use some generic functions, then you need to look into its implementation to see what kinds of requirements are needed for its type. And if you failed to meet the requirement, you'll very likely get several hundred lines of cryptic compiler error message; C++ compilers have been trying very hard to make the error message readable but it's still an awful experience. Also, an implementer now needs to be extra careful when they want to update the function since a single line of seemingly innocuous change may bring breakages for downstream users. Of course this can be prevented by carefully written exhaustive tests, but then what's the point of not having contract?

So the lessons from a number of PL implementations show that this kind of information needs to be explicitly encoded in codes, and that's the whole point of having "contract", "type class", "concept" or whatever else it's called. Compilers may be able to infer technical details of type, but at least for now it's not sophisticated enough to infer the original intention of the writer.

Re:Go 2 Draft Designs by lazyjones on Tuesday August 28, 2018 @05:20PM (#17863007)
Sorry, still don't get it. Extra contract code needs to be written just to prevent "cryptic" compile-time errors? It's just a type mismatch/error like many others to me. Cryptic error messages can be made less confusing by improving the output.

Since Go doesn't have standalone object files / binary libraries, it's not going to produce confusing link-time errors for this.

Re:Go 2 Draft Designs by Too on Wednesday August 29, 2018 @01:13AM (#17865836)
The problem is you don't know if the error is in the type-parameter or if it's in the generic class. Take this very simple c++ program as example, it has 3 potential sources of error and it is not clear from the contract of the foo-function which one is the actual error.

    template <typename T>
    void foo(T bar)
    {
        bar.hardToSpell();        //1. Error here?
    }
    
    struct Bar() {
        void ahrdotspell();        //2. Error here?
    }

    Bar buzz;
    foo(buzz);                    //3. Error here?

In this particular case it's easy to deduce that something is misspelled and error 2 is the real error but the compiler is probably going to tell you it is error 1. And once you get into more complex programs the problem might be that the Bar class is not simply supported by the generic function or that the generic class is implemented incorrectly.

If you instead could add an interface constraint on T (like for example C#/Java/Typescript allows) it would be clear from the contract that this interface defines all the required functions on T if Bar doesn't implement those it is unambiguous that the implementation of the interface is not there.

Re:Go 2 Draft Designs by lazyjones on Wednesday August 29, 2018 @06:03AM (#17867040)
> If you instead could add an interface constraint on T (like for example C#/Java/Typescript allows) it would be clear from the contract that this interface defines all the required functions on

Then you just have a 4th possible spot for an error. I don‘t see an essential difference between considering the function definition as the reference and having a contract (where typos are possible as well), just the latter being cumbersome and superfluous.

Re:Go 2 Draft Designs by Too on Thursday August 30, 2018 @11:05AM (#17877329)
Assuming the interface definition is correct, it gives you one degree less of freedom. Error #1 is always evaluated vs the interface. Error #2 is also always evaluated vs the interface. Error #3 is evaluated vs the type constraint.

So each of the 3 potential errors can always be pinpointed exactly, as opposed to my example where it could be any 3 (or all 3 simultaneously) of them because "T having a hardToSpell-method" is not part of any public interface description, it's something deep in the implementation of the foo-function (in my example it's not very deep but in real code it usually is).

Re:Go 2 Draft Designs by nemetroid on Wednesday August 29, 2018 @12:52PM (#17869723)
Typically you would have the template instantiated for multiple classes (…or there wouldn't be a need for templates). Each class will have its own definition of the functions used on the template argument. If the function definition is the reference, which one?
Re:Go 2 Draft Designs by ianlancetaylor on Tuesday August 28, 2018 @07:14PM (#17863758)
In this case the mismatch is between a type argument and the way that a type parameter is used, so it's not a type mismatch/error, it's a meta-type mismatch error. You are suggesting that the meta-type be inferred from the function (and any functions that it calls) rather than being explicitly stated. That is doable--C++ does it--but it means that the user has to understand the requirements of an implicitly inferred meta-type. The Go design draft suggests instead that the user be required to understand an explicitly stated contract.
Re:Go 2 Draft Designs by summerlight on Tuesday August 28, 2018 @06:35PM (#17863547)
As I mentioned, it's not just for avoiding cryptic error messages, though I am not sure if we're even referring the same thing as this is a completely different one from linker errors. Believe me, improving the output doesn't help that much. Hundreds of C++ compiler developer have been trying that for tens of years. None of them has succeed to the level of making a novice understands what's going on when they give sort(list) to the compiler.

To iterate my point, it serves as a "contract" between users and the code author. Without this, any user of a generic function will implicitly depend on its implementation, which creates tight coupling. Cryptic error messages or unintentional breakage are just undesired side effects from not having this clear boundary. So, the interface of generic functions needs to be explained to its users anyway; then why not making this understandable to compiler and prevent users from making such mistakes?

Re:Go 2 Draft Designs by pjmlp on Wednesday August 29, 2018 @01:19AM (#17865864)
Go does have binary packages, it just happens most devs always build from source.
Re:Go 2 Draft Designs by dangjc on Tuesday August 28, 2018 @02:41PM (#17861596)
I NEED generics to do any quantitative code. I evaluated Go for a project, and completely ruled it out because of this. You're unable to write an algorithm for float 32s and 64s, scalars vs vectors vs matrices, etc.

There might be a bias in the commentary because the membership of the Go community has self selected to just be those for whom the current constraints are feasible.

Re:Go 2 Draft Designs by majewsky on Tuesday August 28, 2018 @05:22PM (#17863026)
If you need a generic algorithm where the possible types are very finite (e.g. just float32 and float64, or just NxM matrices for N,M=1,...,4) you might be able to `go generate` the concrete implementations from a text template.
Re:Go 2 Draft Designs by jacques_chester on Tuesday August 28, 2018 @09:41PM (#17864638)
Text generation is fragile, error prone, does not play well with other type-based tooling, is difficult to upgrade, adds unnecessary busywork to the programmer's day.

When Java's limited, half-crippled version of generics showed up, sourcecode generation died. Pretty much overnight. Why doesn't anyone do it? Because it's a terrible experience compared to having types.

Re:Go 2 Draft Designs by giovannibajo1 on Tuesday August 28, 2018 @05:08PM (#17862896)
You won't be able to do numeric stuff with these proposals as well. You would still be missing operator overloading and parameter of integer types, which are the basis of any generic numeric code.
Re:Go 2 Draft Designs by garfij on Tuesday August 28, 2018 @11:27PM (#17865332)
True about no operator overloading, but that's just syntactical sugar for functions.

I believe you can get integer parameter types by using something like the `convertible` contract seen here https://go.googlesource.com/proposal/+/master/design/go2draf... (unless I'm mistaking what you are saying)

Re:Go 2 Draft Designs by sanxiyn on Wednesday August 29, 2018 @12:40AM (#17865686)
I believe you are mistaking. C++ allows things like std::array<int, 3>, where 3 is parameter of integer types.
Re:Go 2 Draft Designs by Shorel on Wednesday August 29, 2018 @12:52AM (#17865741)
And after that evaluation what did you use?
Re:Go 2 Draft Designs by foldr on Tuesday August 28, 2018 @05:41PM (#17863155)
Fortran does ok without generics.
Re:Go 2 Draft Designs by simias on Wednesday August 29, 2018 @03:44AM (#17866449)
So does C but you don't expect the same things from a language from the 70's. I don't think C or Fortran would be very popular if they were released today.
Re:Go 2 Draft Designs by yiyus on Wednesday August 29, 2018 @09:33AM (#17868068)
I won't argue with that, but I'd just like to say that the newest Fortran versions actually make a quite modern language.

Most of its quirks are related with compatibility with older versions. If a new version without that handicap was released today, it may look nicer than most people think.

Re:Go 2 Draft Designs by foldr on Wednesday August 29, 2018 @06:12AM (#17867074)
Sure, I'm not denying that generics are useful sometimes. It's just that people sometimes exaggerate how big of a problem it is not to have them.
Re:Go 2 Draft Designs by pjmlp on Tuesday August 28, 2018 @05:44PM (#17863180)
Re:Go 2 Draft Designs by foldr on Tuesday August 28, 2018 @06:08PM (#17863376)
>In Fortran 90, user-defined procedures can be placed in generic interface blocks. This allows the procedures to be referenced using the generic name of the block.

I don't know Fortran, but I'm fairly sure that you just googled "fortran generics" and pasted the first result without checking it :)

Re:Go 2 Draft Designs by pjmlp on Wednesday August 29, 2018 @03:14AM (#17866322)
Fortran got simplified generics in 2003, I pasted the wrong link by mistake.

https://cug.org/5-publications/proceedings_attendee_lists/20...

https://software.intel.com/en-us/node/692037

Re:Go 2 Draft Designs by foldr on Wednesday August 29, 2018 @06:11AM (#17867069)
Fair enough, I didn't know about that feature. However, people were using Fortran successfully for writing huge numeric libraries waaaaayyy before that.
Re:Go 2 Draft Designs by pjmlp on Wednesday August 29, 2018 @06:45AM (#17867190)
I was successfully using Z80, 68000 and 80x86 Assembly 30+ years ago as well.
Re:Go 2 Draft Designs by kown223 on Tuesday August 28, 2018 @05:56PM (#17863284)
can't you just use different names, algF32, algF64, really? is this the end of the world? No wander we have npm packages isEven and isOdd, sometimes you need to get yours hands dirty.
Re:Go 2 Draft Designs by andybak on Tuesday August 28, 2018 @01:13PM (#17860646)
You can't legislate against poor taste. Community norms help but there's always exceptions.

It's interesting to consider Python which - generally - has strong community norms against excessive abstractions and too much magic.

There are some notable exceptions. I believe Twisted was regarded as "UnPythonic" and I've heard complaints about asyncio. Interestingly both are related to the same problem space.

I'm sure there are other examples of inscrutable pyramids of abstraction but Python also has many examples of good, readable abstractions.

Maybe it's not abstraction that's the problem but poor judgement? What makes one language sprout AbstractSingletonProxyFactoryBeans and another not? I'm not sure if correlates directly to "ability to create abstractions" - I think there's a human element.

Re:Go 2 Draft Designs by jacques_chester on Tuesday August 28, 2018 @09:47PM (#17864671)
> What makes one language sprout AbstractSingletonProxyFactoryBeans and another not?

Missing features that enable higher levels of composition and abstraction.

Such as, for example, generics.

If you look at the usual punching bag in these discussions, Spring, you will see that as Java added features, the implementations became simpler.

Java's design hypothesis was: if we take away these features, median programmers won't blow their feet off accidentally. But it turns out that to get things done you need well-above-median programmers to provide tools, APIs, frameworks, leverage and that in turn, they will need to find a way to do it. In the case of Spring that's been marked by a slow retreat from heroics into progressively simpler approaches as and when Java itself allowed for them.

Spring 5, for instance, sets Java 8 as the minimum, and they went through the whole framework refactoring, cleaning up, cutting down and so on wherever that baseline allowed them to.

Disclosure: I work for Pivotal, which sponsors Spring, though on unrelated software. But I've spent a lot of time with Spring folks. They are smart.

Re:Go 2 Draft Designs by marcosdumay on Tuesday August 28, 2018 @05:13PM (#17862940)
> What makes one language sprout AbstractSingletonProxyFactoryBeans and another not?

On this case, it's the lack or availability of alternatives. You can't take away every feature that isn't the strictest possible OOP and expect people to create expressive and simple code. Remember that those things were created by the best professionals around, and won the selection of best practices and standard open source tools.

People do not write singletons in Python because it has actual static variables. Any moderately complex Python code is full of factories, but people don't even notice because they are actually just a function declaration around the same code that would be there anyway. There is a lot of "writing too the interface" that Java people do with abstract classes, but it comes nearly automatically with duck typing. And for the "bean" part people just use dictionaries.

Go people seem to be taking the wrong lesson from those things.

Re:Go 2 Draft Designs by random3 on Tuesday August 28, 2018 @03:08PM (#17861885)
> I believe Golang has two different kinds of productivity. Productivity within the project goes up quite a lot with generics. And then, everyone tends to immediately treat every problem as "let's create a mini language to solve this problem". The second type of productivity - which is getting more and more important - is across projects and codebases. And that gets thrown out of the window with generics.

This is a very valuable observation, relevant outside of Golang, which underlines the pitfalls of abstractions. Design patterns aim to standardize abstractions so that other readers of the same code can easily understand.

I used to capture the same related principles in what I called "IKEA code" - simple, elegant code that is cheap to write, easy to understand and use and not meant to last forever. I.e. code and design that is meant to be replaced. I think the concept of "local productivity vs global productivity" is very related and completes the "IKEA code" principles. Rather than suggest one is better than the other, I think it's important to understand the motivations when making a choice.

Re:Go 2 Draft Designs by platinumrad on Tuesday August 28, 2018 @02:28PM (#17861453)
>The second type of productivity - which is getting more and more important - is across projects and codebases. And that gets thrown out of the window with generics.

Generics increase type safety (no more interface{} casts) and reduce code duplication. I don't see how this could possibly throw productivity "out the window". If anything, the effect will be the opposite. The tradeoff with generics has always been programmer time versus compile time and/or execution time. Assuming that programmers don't unnecessarily complicate things for themselves, programmer time will be significantly lessened with the introduction of generics. And there's nothing preventing programmers from burying themselves in a sea of abstraction even in a language without generics.

Re:Go 2 Draft Designs by jballanc on Tuesday August 28, 2018 @02:08PM (#17861233)
> One cannot have both I guess?

Not to be snarky, but...

The whole point of LISP-style macros is that you very much can have both. Ultimately, generics will compile down, either via type erasure or a generated specialization, to a "copy-pasted" function (in concept, at least). With a macro, you have ultimate control of how this is achieved.

The problem, of course, is that the people who care how generics are implemented all think their way is the best (leading to a proliferation of slightly-different-and-incompatible implementations), and everyone else just wants something that works fast and reliably.

Bad code can be written in any language. Good code can be written in most languages (yes, even C++...the jury is still out on PHP). Every feature that grants power comes at the cost of potential complexity. What ultimately determines success or failure is the community and best practices that develop around these features.

In this regard, I think Go will be "o.k." even with generics.

Re:Go 2 Draft Designs by KirinDave on Tuesday August 28, 2018 @03:24PM (#17862034)
> But then, after seeing the examples, e.g. https://github.com/albrow/fo/tree/master/examples/, I could see the picture of what the current codebase would become after its introduced. Lots of abstract classes such as "Processor", "Context", "Box", "Request" and so on, with no real meaning

> Compared to a half-as-useful Java codebase where I have to carry a dictionary first to learn 200 new english words for complicated abstractions and spend a month to get "assimilated", this was absolute bliss

You're making a good argument for standard generics and their machinery included as part of the standard library as opposed to bolted on.

Java incrementally baked generics in relatively late in its life along with a culture of a lot of ad hoc machinery to cover up the lack of useful lambdas.

The wisdom of Go putting these in the stdlib is you get their benefit universally without having to wade through a learning process with a uniquely flawed and ad hoc hierarchical ontology for each project.

Having such universal tooling is a sign that your language is powerful enough to lift out and abstract real problems. That's a good thing! Don't mistake Java's legacy issues for issues Golang might have. It probably won't end up with the same problems because it starts with a better feature set.

Re:Go 2 Draft Designs by JepZ on Tuesday August 28, 2018 @01:25PM (#17860758)
I am not quite fond of the idea of having C++/Java Style Generics (I simply don't like the syntax that comes with it), but I see that the current system is broken.

From my current perspective I think fixing some things related to Go Interfaces and Container types (Maps/Slices) should make them even more usable than they are now and making them pretty much the thing people want to use Generics for. Currently, it looks like hell to build something with the empty interface and using a lib which is built around the empty interface doesn't look nice either.

Using Go maps is sometimes awkward too as they require some weird attribute 'comparable' which some types posses and others don't. Why??? I mean why can't the Go authors use their own language construct and use an Interface like:

  interface Comparable {
    Comparable(interface{}) bool
  }
Similarly, I find it awkward that we still can't use Interface Slices[1]. I mean I understand it isn't simple to implement but certainly not impossible.

One thing on my todo list is writing an experience report with better examples. It's priority just got up-voted ;-)

[1]: https://github.com/golang/go/wiki/InterfaceSlice

Re:Go 2 Draft Designs by heavenlyhash on Tuesday August 28, 2018 @01:37PM (#17860894)
Counterpoint: coming from a Java background, I find totally freely-definable interfaces for some features used by core container types to be a little worrysome.

In Java, I can't count the number of times I've debugged either correctness bugs or 'merely' horrible performance bugs based on incorrect implementations of Equals or Hashcode methods. Implementing a non-commutative Equals method is a colossal footgun, and incredibly irritating to debug, and yet somehow it happens time and again.

And there are other, subtler, arguably "correct" and yet but extremely unwise things one can when do given Java-like maps implemented on the Equals and Hashcode interface methods. For example, one can define two types T1 and T2 which both claim to be (commutatively) equal, and define some interface TX which is implemented by T1 and T2. Using a Map<TX,Object> and inserting members by T1 and T2 now has an interesting form of semi-defined behavior: if inserting "equal" keys, whichever type was used first will be persisted. Imagine doing this in some concurrent map, and imagine that T1 is 8 bytes and T2 is 400 bytes; enjoy debugging those occasional OOMs.

I've been very happy not to ever have this particular problem when defining the key types in my Go maps.

Re:Go 2 Draft Designs by dtech on Tuesday August 28, 2018 @02:25PM (#17861408)
Java does equals and hashCode horribly. Granted, they did not have Java to learn from but it's what we have.

Kotlin and Scala solve the problem pretty decently. Equals and hashCode are automatically generated for data/case classes. I've never encountered a messed up equals in Scala and only very rarely felt the need to override the generated equals, and then you make a very conscious choice to do it.

C# does it even better, there is a IEquatable<T> interface that defines the `bool Equals(T other)` method. It partially solves the irritating universal equality.

If I would design Java today Object would have no methods and there would be a stdlib interface defining `equals(other: T)`, and data classes would automatically implement that interface

Re:Go 2 Draft Designs by naasking on Tuesday August 28, 2018 @04:43PM (#17862690)
> If I would design Java today Object would have no methods and there would be a stdlib interface defining `equals(other: T)`, and data classes would automatically implement that interface

This polymorphic equality is the default in some functional languages, like OCaml. It's fine for simple cases, but you really do need overloadable equality. Equality as a method in OO is a problem because of the asymmetry though, and often an even bigger problem because such languages typically permit pervasive null.

Re:Go 2 Draft Designs by dtech on Thursday August 30, 2018 @05:58AM (#17875417)
There definitely are cases where that's not enough, but it's a 95-99% solution.

The problems you mentioned:

Classes could change equals to accept subclasses. Then subclasses could not alter equality themselves.

T implementing `equals(other: U)` for some U solves a lot of other use-cases, but could make equality asymetrical.

Reference equality would still exist, but would not be the default, e.g. Java's `equals` is Scala's `==`, and Java's `==` is Scala's `eq` operator (which you almost never use)

Re:Go 2 Draft Designs by naasking on Thursday August 30, 2018 @12:08PM (#17877826)
Re:Go 2 Draft Designs by hellofunk on Tuesday August 28, 2018 @02:25PM (#17861413)
I recently had to write my own equals and hashcode functions in a Java project (a language relatively new to me) just so I could store my custom object as a key in a HashMap. The experience of doing this seemed so silly and unnecessarily low-level to me, that I almost abandoned the whole codebase and looked for another language to start over.
Re:Go 2 Draft Designs by JepZ on Tuesday August 28, 2018 @02:32PM (#17861495)
Well, there is another problem with my suggestion: At the moment, Maps have no problem using custom structs as they stack up the comparable attribute of the containing fields. If you would use a normal interface you would have to define how you would want to name that kind of relation (all fields of X implement interface Y so X implements Y? Sounds pretty similar to how the equal operator works in Go). Otherwise, you would have to implement Comparable for every custom type which would be in fact even worse than the current state (It is bad enough we have to do that for the sort.Interface twice per week ;-).

So I completely agree, that having to implement basic attributes like 'equals' or 'comparable' is no good idea. Instead I would favor some logic which assumes some natural situation and lets you implement a custom logic if you want to do it.

Nevertheless, I think those problems just show some of the inconsistencies Go comes with. Don't get me wrong, I love Go and I like the way the Go devs work. It is just that I am worried that we will end up with Go 2.0 adding Generics without solving the issues within the otherwise pretty nice Interface system.

Re:Go 2 Draft Designs by zlynx on Tuesday August 28, 2018 @01:45PM (#17860978)
Go could automatically create hidden Test methods for methods used by core types like maps. If Equals and Hashcode have to be correct, then these tests could ensure it.
Re:Go 2 Draft Designs by naasking on Tuesday August 28, 2018 @03:52PM (#17862271)
> C++/Java Style Generics

C++ and Java generics are nothing alike, so there's no such thing as C++/Java-style generics.

Re:Go 2 Draft Designs by JepZ on Wednesday August 29, 2018 @04:48AM (#17866766)
In fact, I am not completely sure about the state of Generics in C++. AFAIK the term 'Generics' was coined in context of Java, but C++ has a similar concept they call Templates. Maybe you could elaborate on what is the exact difference between those two concepts?
Re:Go 2 Draft Designs by mike_hearn on Wednesday August 29, 2018 @05:55AM (#17867014)
Templates can do a lot more than generics can, but come with corresponding downsides.

Templates are basically a form of copy/paste style substitution with fancy bits. When you instantiate std::vector<char> in C++, the compiler creates an entirely new class with "char" substituted in everywhere the type variable appears. This class has nothing in common with std::vector<MyStruct> - there's no common superclass, the compiled code may or may not be shared depending on low level details of your toolchain and the types involved, etc. That in turn means if you want to write a function that works for any std::vector you must also use templates, and your function will also be substituted, and your final binary will also have many similar-but-different copies of the compiled code, etc. However because of how C++ templates work you can achieve some pretty astonishing things with them. In particular you're getting code compiled and tuned to the exact data type it was instantiated with, so you can go pretty fast with certain data layouts.

Java generics seem superficially similar but in fact are different. In (erased) generics, a List<Foo> and List<Bar> are exactly the same class at runtime. They're both just List and both just contain objects. The compiled code is the same, you can cast between them if you know what you're doing, etc. Likewise if you write a generic function that works for any list, there's only one copy of that function. Generics have different tradeoffs: they're less powerful (you can't write a regex library with them for instance), and they don't auto-tune themselves to particular data types ... at least not until Project Valhalla comes along ... but they're backwards compatible with pre-generic libraries at a binary level and they avoid an explosion of compiled code bloat, which is a common problem with templates.

Re:Go 2 Draft Designs by JepZ on Friday August 31, 2018 @11:40AM (#17886438)
Thanks for clarifying, sounds like pretty deep stuff though.
Re:Go 2 Draft Designs by gshrikant on Tuesday August 28, 2018 @09:55PM (#17864720)
Can you point me to a resource with details about this? I'm relearning C++ and a comparative evaluation of a language feature like that would be very useful.
Re:Go 2 Draft Designs by pjmlp on Wednesday August 29, 2018 @03:28AM (#17866373)
Check Tour of C++, 2nd edition is updated for C++20.
Re:Go 2 Draft Designs by wtetzner on Tuesday August 28, 2018 @09:21PM (#17864483)
I think they were just referring to the angle-bracket syntax.
Re:Go 2 Draft Designs by stcredzero on Tuesday August 28, 2018 @05:01PM (#17862845)
I see that the current system is broken.

Just where is the line between "tedious but workable" and "broken?"

Re:Go 2 Draft Designs by oihoaihsfoiahsf on Tuesday August 28, 2018 @02:06PM (#17861209)
> "Processor", "Context", "Box", "Request"

There are a lot of interfaces in the existing library that one could consider quite abstract as well. Reader? Writer? error? Another thing worth noting is that many/most C++ codebases manage to avoid the type of generic proliferation you're talking about.

Re:Go 2 Draft Designs by mike_hearn on Tuesday August 28, 2018 @02:22PM (#17861384)
I'm not sure C++ is a great example of a language that avoids generics abuse. The reason STL errors are so convoluted is largely due to the unintuitive and complicated way they use generics to support obscure features like changing the allocator used by containers.

Java is actually a much better example of where generics are used rarely and well. Containers are parameterised by exactly one thing - the type of what they contain. You don't parameterise them with different allocation strategies or comparators. Type inference means generics are often automatic, but still catch mistakes for you. And whilst nothing stops people making bad abstractions in any language, the standard library sets a pretty good example by and large.

That said, Kotlin's generics are better still and probably the best implementation I know of.

Re:Go 2 Draft Designs by grandmczeb on Tuesday August 28, 2018 @03:33PM (#17862118)
> The reason STL errors are so convoluted is largely due to the unintuitive and complicated way they use generics to support obscure features like changing the allocator used by containers

The main reasons template errors suck so much in C++ are 1) lack of a proper mechanism to constrain instantiations (hopefully addressed by Concepts) and 2) The general mess that is function overloading and automatic type conversions.

For example, the classic "template hell" error message people usually encounter when starting to use C++ is failing to properly overload operator<< (example here[1]). That error message could easily be as simple as "No `operator<<` for class C", but instead the compiler needs to inform the user of every possible overload match, every possible type conversions that could cause a match, and templates that could have matched but can't be instantiated along with a reason for the failure. Of course it doesn't help that std::ostream is absurdly abstract, but it's really just making a bad problem worse rather than the fundamental root of the problem

[1] https://godbolt.org/z/XveitP

Re:Go 2 Draft Designs by oihoaihsfoiahsf on Tuesday August 28, 2018 @04:03PM (#17862360)
I think it's 100% ok for a big utility library like boost or std to have complicated internals to support a variety of use cases. The go standard library likewise is big and complicated (although perhaps not quite as). My main concern is that user code can be written simply. And to be clear, I'm not holding up C++ as an example of a great language. In fact, I'm kind of looking at it as a worst-case scenario. I'm only saying that most C++ programs I've been exposed to are relatively free of creeping genericity.
Re:Go 2 Draft Designs by naasking on Tuesday August 28, 2018 @04:45PM (#17862700)
> The reason STL errors are so convoluted is largely due to the unintuitive and complicated way they use generics to support obscure features like changing the allocator used by containers.

The reason STL errors are so convoluted is because the C++ template language is Turing complete.

Re:Go 2 Draft Designs by jcelerier on Tuesday August 28, 2018 @07:19PM (#17863806)
no, it's because every function is implemented with a dozen helper function so compiler error stack traces have to show all the intermediate, generally return-only, helper functions
Re:Go 2 Draft Designs by pjmlp on Wednesday August 29, 2018 @03:30AM (#17866389)
True if we are speaking about C++11 and earlier.

With C++14 onwards, it is a matter of developers actually making use of static_assert, constexpr if and enable_if.

Not as comfortable as just using concepts, but they get the job done.

Re:Go 2 Draft Designs by naasking on Wednesday August 29, 2018 @08:19AM (#17867626)
> no, it's because every function is implemented with a dozen helper function

Which are needed and/or allowed for reuse because the template language is Turing complete. More restrictive type-level languages have better error messages because the compiler either understands what you're intending to do or you're limited in the things you can express, full stop.

Re:Go 2 Draft Designs by orblivion on Tuesday August 28, 2018 @01:28PM (#17860791)
I'd say generics aren't just about avoiding copy-pasting. It's also added type safety. At this point the closest thing is using an interface as a function parameter. You get a dynamically typed value (albeit limited to types that implement the interface).
Re:Go 2 Draft Designs by sacado2 on Tuesday August 28, 2018 @03:42PM (#17862190)
That, and efficiency, as the generated code can be inlined in many cases.
Re:Go 2 Draft Designs by lima on Tuesday August 28, 2018 @02:26PM (#17861417)
The closest thing is auto-generating code, not using interface{}.
Re:Go 2 Draft Designs by platinumrad on Tuesday August 28, 2018 @02:34PM (#17861527)
Yes, but there's still a depressingly large amount of code in the wild that just casts interface{} back and forth.
Re:Go 2 Draft Designs by lima on Tuesday August 28, 2018 @02:40PM (#17861585)
Common with ORMs. The gorm API is horrible - it's all interfaces.

The only reasonable ORM library I've seen is sqlboiler, which uses code generation.

https://github.com/volatiletech/sqlboiler

Re:Go 2 Draft Designs by orblivion on Tuesday August 28, 2018 @05:57PM (#17863291)
I don't necessarily mean interface{}. This:

type Thing interface { ... }

is better, but Thing is still a dynamic type.

Re:Go 2 Draft Designs by chrnad on Tuesday August 28, 2018 @01:23PM (#17860735)
I think it's hard to get a feel for how it would look in practice from those short examples.

Library code might be a little ugly and abstract, but as an end-developer, you usually don't need to worry about it. The code you yourself would see and write is going to have a lot more meaning and be more understandable.

I've rarely had to do anything fancy with generics in my own projects. Where I've seen it be most useful is when I want to offer a flexible public API -- in which case, the choice of writing a bit of generic library code is much less smelly than copy pasta.

Re:Go 2 Draft Designs by ori_b on Tuesday August 28, 2018 @02:26PM (#17861418)
> Library code might be a little ugly and abstract, but as an end-developer, you usually don't need to worry about it.

But the functions you provide for the code you're writing are a library for someone else.

Re:Go 2 Draft Designs by sdegutis on Tuesday August 28, 2018 @01:19PM (#17860694)
> Lots of abstract classes such as "Processor", "Context", "Box", "Request" and so on, with no real meaning.

This is a completely false dichotomy. Just because a feature can be misused doesn't mean it's not legitimately useful. Generics make the language easier for the user, but are harder for the implementors. Most language designers / implementors recognize that this trade-off is worthwhile, and therefore nearly every other popular typed language has them. The Go implementors are the only ones against doing it, because, well, they would have to implement it, and they're concerned that it will make the codebase too complex for them to maintain. (Their sympathizers are against it too, which is still a mystery to me.)

Re:Go 2 Draft Designs by jy3 on Tuesday August 28, 2018 @03:11PM (#17861911)
> Just because a feature can be misused doesn't mean it's not legitimately useful.

The point isn't that it can't be useful.

In the real world, the amount of code I'm forced to understand that uses overly complicated abstractions is the issue. I'm glad one language finally took the opposite direction.

Re:Go 2 Draft Designs by munificent on Tuesday August 28, 2018 @07:16PM (#17863773)
> In the real world, the amount of code I'm forced to understand that uses overly complicated abstractions is the issue.

This may say more about the specific codebases you work in than it does the software world at large. I spend most of my time in a couple of languages that all have generics and don't experience the problem you describe.

Re:Go 2 Draft Designs by pwm on Wednesday August 29, 2018 @06:04AM (#17867046)
There are good and bad abstractions. In my experience good ones are usually grounded in math. Used the way they are intended generics/parametric polymorphism should reduce your cognitive burden. Eg. having a single, well defined and tested abstraction like Set that is type safe and its operators can work on any type it can contain is surely a good and worthwhile abstraction. The same goes for parametrically polymorphic functions that need not know about the concrete types they operate on and with the proposed contracts they can optionally require that its argument types possess a given constraint/capability like equality.
Re:Go 2 Draft Designs by nemothekid on Tuesday August 28, 2018 @02:55PM (#17861752)
I'd argue that Generics make the language easier for the writer, not the reader which is what he was getting at. What I like about Go is the language is small, so at the expense of some verbosity, that in most cases you write once, its very easy to understand. One thing I dislike about some Java & Scala codebases is the "manual" unwinding you have to do to debug some functionality.
Re:Go 2 Draft Designs by whateveracct on Tuesday August 28, 2018 @03:22PM (#17862009)
This is FUD.

Parametric polymorphic code is not hard to read at all - in fact, it is easier to reason about since it is universally quantified for all types.

Re:Go 2 Draft Designs by chowells on Tuesday August 28, 2018 @04:07PM (#17862401)
Most people don't even know what parametric polymorphism is, let alone have ever used a language that supports it. I find it's basically impossible to explain just how powerful of a tool it is to someone who lacks experience using it.
Re:Go 2 Draft Designs by aikah on Tuesday August 28, 2018 @04:38PM (#17862643)
"append","delete","copy" in Go is parametric polymorphism hardcoded in the compiler. append can be called with many different array types. There is nothing complicated with that.

go can iterate over arrays irregardless of the element type the same way with the same construct using "range", therefore "range" is polymorphic.

The real debate here is should the compiler be "privileged" or should there be API in userland to implement these behavior.

Re:Go 2 Draft Designs by sdegutis on Tuesday August 28, 2018 @04:14PM (#17862445)
> Today it exists in Standard ML, OCaml, F#, Ada, Haskell, Mercury, Visual Prolog, Scala, Julia, and others.

> Java, C#, Visual Basic .NET and Delphi have each introduced "generics" for parametric polymorphism.

https://en.wikipedia.org/wiki/Parametric_polymorphism

Re:Go 2 Draft Designs by chowells on Tuesday August 28, 2018 @06:33PM (#17863536)
A bunch of low-reach languages have true parametric polymorphism. A bunch of common languages have polymorphism that may be parametric or may be bounded by runtime type information checks, and you can't tell the difference from the types.

Neither of those contradict my assertion that most programmers have never done work in a language where the type system can make guarantees that they can trust.

Re:Go 2 Draft Designs by whateveracct on Tuesday August 28, 2018 @08:16PM (#17864082)
This is a very pedantic point
Re:Go 2 Draft Designs by whateveracct on Tuesday August 28, 2018 @04:58PM (#17862822)
The only programmers who haven't used a language with parametric polymorphism are those who have only programmed in C, Go, or dynamic languages at this point.

Outside of Java syntax noise, I really have my doubts that Java's parametric polymorphism is too complicated for the average programmer to understand.

  public static <A> A identity(A a) { return a; }
Re:Go 2 Draft Designs by chowells on Tuesday August 28, 2018 @06:30PM (#17863522)
Java does not have parametric polymorphism because instanceof exists in the language. That reduces what you can say about something from the type alone to "maybe parametric, maybe bounded by runtime checks that aren't visible in the type."

How many languages provide you a way to guarantee at the type level that the behavior of a function cannot be influenced by instantiation of type variables? I don't believe that to be true of anything that runs in the JVM or in .NET, for instance, as runtime type information is always available. C++ has dynamic_cast. What common language actually has parametricity expressed in the type system?

Re:Go 2 Draft Designs by whateveracct on Tuesday August 28, 2018 @08:01PM (#17864009)
That’s true..but Haskell has bottom and Scala has bottom + instanceOf checks and JVM reflection as well. And they clearly have usable parametric polymorphism despite things being “broken.”

Saying Java doesn’t have parametric polymorphism because you can cheat is like saying Haskell isn’t pure because of unsafePerformIO.

Re:Go 2 Draft Designs by pwm on Wednesday August 29, 2018 @06:08AM (#17867059)
Agreed. There is always a point where it's the developer's responsibility to write good code, even in languages where it's very difficult to shoot yourself in the foot.
Re:Go 2 Draft Designs by al2o3cr on Tuesday August 28, 2018 @07:28PM (#17863856)
> Lots of abstract classes such as "Processor", "Context", "Box", "Request" and so on, with no real meaning.

A programmer can write Java in any language if they're willing to work hard enough at it.

Re:Go 2 Draft Designs by pjmlp on Wednesday August 29, 2018 @03:32AM (#17866396)
Actually Java adopted those ideas from 90's C++ code style.
Re:Go 2 Draft Designs by norswap on Tuesday August 28, 2018 @04:47PM (#17862730)
Complete bullshit. Generics have 0 relationship or co-dependency of any kind with the abstraction slash design patterns you mention. These are entirely possible without generics, and generics does not in any way encourage them.
Re:Go 2 Draft Designs by stcredzero on Tuesday August 28, 2018 @04:57PM (#17862813)
There are less common design patterns particular to generics. The presence of generics does tend to encourage those. I have seen subsystems where coders used C++ templates where they could have used polymorphism instead.
Re:Go 2 Draft Designs by nostrebored on Tuesday August 28, 2018 @04:55PM (#17862794)
... I'm sorry, that's a bold claim when a large chunk of these patterns are literally used to allow for you to be able to operate over a variety of different objects in a loosely coupled fashion
Re:Go 2 Draft Designs by jy3 on Tuesday August 28, 2018 @03:15PM (#17861945)
My gut feeling is a significant part of people who voted for them don't really intend to use Go that much.

They might try to please different crowds with Go 2. At the end of the day, they might just loose everyone.

Re:Go 2 Draft Designs by mikeschmatz on Tuesday August 28, 2018 @01:39PM (#17860907)
Poor design has nothing to do with generics. If anything they make API cleaner and safer to work with.
Re:Go 2 Draft Designs by manigandham on Tuesday August 28, 2018 @04:39PM (#17862651)
Having generics isn't related to excessive abstractions. One is a language feature and the other is program architecture. It's definitely not an exclusive trade-off.

I'm sure there are plenty of Go apps with bad architecture, where a tiny dose of generics would greatly help.

Re:Go 2 Draft Designs by stcredzero on Tuesday August 28, 2018 @04:59PM (#17862831)
Having generics isn't related to excessive abstractions.

I've seen the situation in C++ where templates led to excessive templates, simply because they were "neat." As a result, I found myself debugging code that had no source code whatsoever.