
Go Proposal: first-class support for sorting slices - giovannibajo1
https://github.com/golang/go/issues/16721
======
patates
So the current approach is providing some popular functions which would
normally require generics to implement as built-ins?

~~~
quotemstr
I was just ranting about this approach elsewhere. Go and QBasic are broken in
the same way: both lack power in the core language and have special syntax for
facilities that really ought to be normal calls into the standard library. In
Go's case, we have goroutines, error flag omission, maps, and so on; in
QBasic, we have LINE.

A language's core syntax should not privilege its standard library above other
libraries.

~~~
stcredzero
_A language 's core syntax should not privilege its standard library above
other libraries._

I'm not so sure. Smalltalk had this in spades. There is a downside to this.
Giving a bunch of 20-somethings the full power to basically change everything
can result in code-bases which suffer from the chaos of over exuberant hubris.
Go is deliberately favoring a certain set of _conventions_. To do this, they
are also deliberately making it harder to change the language from within
itself.

~~~
sbov
It's not about changing everything, it's about being able to make abstractions
that aren't second class citizens. By giving this power, you also increase the
consistency of the language.

~~~
stcredzero
_By giving this power, you also increase the consistency of the language._

Maybe. That's like the apocryphal story about the student asking a question if
a particular proof step is really obvious, so the professor goes across the
hall, derives stuff on the other blackboard for the next 30 minutes, then
comes back into the lecture hall saying, "Yes, it's obvious."

Maybe you increase the consistency of the language from one point of view, but
what happens from the perspective of each individual project? What if this
leads to projects where templates have been used to create 3 different
template based "little languages" to make X, Y, and Z easier? You had 3
problems, but now you have 6. The oft written reply to that in these debates,
is to limit the power of the template system -- but is that a robust goal
under the group dynamics of the language community? I think not.

One subliminal goal in the design of Go seems to be about privileging certain
_conventions_ to avoid a babel of roll-your-own conventions in large projects.
This is all across the language and even in the toolchain.

~~~
catnaroek
The problem with templates is that they're ad-hoc: they can be specialized,
and they're only checked at instantiation time. C++'s type level is literally
a dynamic language, and template errors are literally stack traces, only made
worse by backtracking, due to the deepest unification rule and SFINAE.

But bona fide parametric polymorphism doesn't have this problem. ML's design
is a constructive proof that you can have a reasonable degree of abstraction
without compromising usability.

------
eknkc
It seems like due to lack of generics I see more and more interface{} and
reflection stuff in code bases. This is getting ridiculous.

I've written a lot of Go. Tried my best to stick to what language provides but
at some point you say "screw it" and start fighting with the language. That is
never a good sign.

~~~
shurcooL
Why hasn't it happened to me? I've been writing Go for over 3 years, and I
prefer the language stay as is. I'm more concerned about porting it to more
platforms. Perhaps that's a reason I'm motivated to desire less language
changes.

~~~
coldtea
> _Why hasn 't it happened to me?_

Well, don't know about your case, but I've seen e.g. people who are religious
about being DRY and dislike any kind of useless boilerplate, and others just
copy paste code with wild abandon and couldn't care at all.

~~~
eknkc
Also, I'm generally fine with language tradeoffs, If there is a good reason
that I need to copy paste something, so be it. I'll do it.

Go and Generics issue on the other hand, feels a little different to me. It is
a solved problem. Go does not have an inherent show stopper for generics. It's
just not there because of.. What? Stubbornness? I'm not sure. But then it
irritates me to copy paste stuff.

~~~
shurcooL
> It is a solved problem.

This is debatable. Is it a problem that's solved well? Is it solved in the
best way possible and there could never be a better way to do generics?

I think not. I think it's solved adequately, but not great. Compared to the
other facilities that Go offers, generics are typically pretty messy and add
significant complexity to the language, tools, parsing, reasoning, compilation
times, etc.

> It's just not there because of.. What? Stubbornness? I'm not sure. But then
> it irritates me to copy paste stuff.

This statement is ill-informed. Have you seen
[https://github.com/golang/go/issues/15292](https://github.com/golang/go/issues/15292)
and
[https://github.com/golang/proposal/blob/master/design/15292-...](https://github.com/golang/proposal/blob/master/design/15292-generics.md)?
Have you considered all the ways in which it will affect the language and the
trade-offs?

Once generics are added to Go, they will forever be there, together with all
the disadvantages and missed opportunities, and we'll have to live with them.
That's not a thing to be taken lightly.

In comparison, maybe copying a little here and there isn't all that bad.

------
bigdubs
Another approach to this (this is used to good effect in LINQ) is to skip the
`Less(i,j)` and just provide a value extractor, except golang makes that super
verbose because you'd have to do `func(v interface{}) interface{}`

The idea would be if you have `type foo struct { ID int, Rank int }` you could
provide `func(v interface{}) interface{} { return v.(foo).Rank }` and it would
sort by rank.

Some level of late binding / genericity would be necessary to make this
approach not as verbose.

~~~
masklinn
> Another approach to this (this is used to good effect in LINQ)

Also in Python, it's called "key functions". Of course since Go doesn't have
tuples and/or user-defined ordering, it either only works for simple
comparisons (e.g. by rank but not by rank and name) or you have to hand-roll
some weird-ass coercion into whatever key type the language uses.

> you'd have to do `func(v interface{}) interface{}`

And that doesn't actually work, interface{} is not orderable. Only integers,
floats and strings are "naturally" orderable.

~~~
bigdubs
Also time.Time (which could be thought of as two int64s)

Even string ordering there is a lot left up to the implementation as far as
how it is done. Do capitals come first? Does capitalization not matter? etc.

For non-intrinsic types you would provide the equivalent `less` function, but
in my own programming the bulk of the things I order by are intrinsic.

------
ainar-g
I may be an outlier here, but I'm not bothered at all by the way sorting is
currently done. It's good enough. The "tedious" type names are mostly
unexported anyway, and Len and Swap methods are just a bit of copy-paste.

I don't really think we should tweak it, it's not broken. A code-generation
tool would be nice instead.

~~~
coldtea
> _I may be an outlier here, but I 'm not bothered at all by the way sorting
> is currently done. It's good enough._

I fear that's also the motto for a lot of Go's design choices.

~~~
stcredzero
Don't fear. Be assured!

------
icholy
That interface{} parameter makes me cringe, but it makes sense.

~~~
spriggan3
Go needs functions that support parametric types for collections. I'm not even
talking about generics here as user defined types. Let's forget about generics
or "the ability for developers to implement their own type safe containers".

Let's talk about the fact that functions in Go could support type parameters
in signatures , something like :

    
    
       func Map<V,W>(slice []V,func(element V)W)[]W {
          // ...
       }
    
    

What we have here is a guarantee that at compile time, this code is safe. We
didn't introduce generics, slice is a Go slice of V and the result is a go
slice of W.

The code should then be used this way :

    
    
        result := Map<string,string>([]string{"a","b"},
            func(e string)string{ return e+"foo" } )
    

This is completely type safe, no reflection is used, the compiler knows all
the types at compile time and no generic type was introduced. This is a good
trade off and merely syntactic sugar that would enable developers to get rid
of interface {} parameter + type assertions.

~~~
catnaroek
This is nice, but generic functions are still generics.

~~~
spriggan3
Go already has generic functions : append, copy ... that are type safe at
compile time, how do you think they are implemented in the source code of Go's
compiler?

Just like I said. Go compiler finds "append" token, and go look up if both
arguments and the return type match, not at run time, at compile time.

~~~
catnaroek
No disagreement. I was just pointing out that what you were asking for is in
fact user-defined generics.

~~~
scott_s
In fact, if I understand spriggan3's proposal correctly, that's how Java's
generics work. The approach is usually called type-erasure.
([https://docs.oracle.com/javase/tutorial/java/generics/erasur...](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html))

------
frou_dh
> naming a new type (e.g. "widgetsByName") is tedious to many

More than tedium, it's a bit sinister because the convention of creating
'parallel' slice types with names like that blurs the line between what's a
noun and what's a verb. With a type name like that, one would expect a value
of that type to always be sorted, right? Nope! A "widgetsByName" is just a
flower in the breeze hoping that the sort.Sort bumble-bee makes contact.

------
karma_vaccum123
Yes.

Brad is correct, the current approach is tedious.

------
sdegutis
<off-topic>Since when did Go use Github for official proposals? Does it also
use the Github repo for official development or is it still just a
mirror?</div>

~~~
giovannibajo1
The new proposal process is documented here, and goes through opening a GitHub
issue:
[https://github.com/golang/proposal](https://github.com/golang/proposal)

Go "partly" uses GitHub. The git repo is a mirror, and code review / pull
requests is done through Gerrit, but the issue repo is the official one.

