15 ms·
Go Proposal: first-class support for sorting slices
- sdegutis 10y ago<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 10y agoThe 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.
- karma_vaccum123 10y agoYes. Brad is correct, the current approach is tedious.
- patates 10y agoSo the current approach is providing some popular functions which would normally require generics to implement as built-ins?
- giovannibajo1 10y agoI think they should at least implement a few builtin functions (that can be "real" generics) for common stuff that manipulate slices and/or maps. I'm thinking things like min/max, which are really distracting and are concepts that are more easily expressed as a concise function rather than an explicit loop.
- mattnewton 10y agoI understand the want to avoid over architected designs, but relying on a single party (who is not associated with your product or business need) to bless every abstraction you can use in your code base seems like a recipe for pain and awkwardness. Definitely limits me from wanting to make significant investments in go.
- limsup 10y agohttps://golang.org/LICENSE https://golang.org/LICENSE
- mattnewton 10y agoRight, so now I'm forking it and maintaining my own language to add a feature I just get for free in any number of reasonable competitors..
- karma_vaccum123 10y agoRust is ready, free, and open. Use it and stop complaining about Go.
- mattnewton 10y agoIn my case it's python, Rust has a bit more of a learning curve / productivity hit. I'm still complaining though because I like what Go is doing with concurrency and simplicity, but I think it would be almost perfect if it just trusted the user a bit more.
- woah 10y agoYou say you like the simplicity, yet you are complaining about it.
- mattnewton 10y agoBesides the fact that I think it's less simple to have ad-hoc compiler extensions for the standard library types that can't be replicated in userspace, so the alternatives are code generation and type erasure, it doesn't have to be an absolute principal! We can have generics without sliding towards some slippery slope of abstraction! You don't allow some kind of generics one day and wake up the next day with custom operators and monads. The buck really can stop at this one pain point.
- quotemstr 10y agoI 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 10y agoA 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 10y agoIt'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 10y agoBy 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.
- pjmlp 10y agoOr use code generation via the generate package. Go is a great C replacement for any use case where using a GC is an affordable option. Other than that, there are lots of other languages with AOT compilation to native code and better abstractions.
- pkaye 10y agoCan you give an example of what exactly generate does? All I can tell is that it me you call other programs like yacc to preprocess some files. So just a replacement for make?
- frou_dh 10y agoIt's basically the storing of a verbatim one-line command as a line comment in a .go source file rather than its traditional home of a line in a shell script or makefile. Imagine you found it intolerable to have an interpreter-dependant -- not even /bin/sh -- source file in your package directory (said another way, anything but .go source files in the package directory), but at the same time needed to somehow sneak in the functionality of a rudimentary shell script. The answer? Weave it into a .go source file and the Go toolchain will be able to pick up on and execute it (on demand, never automatically).
- wyager 10y agoIf I can use GC, why would I pick go over any of the other compiles-to-native languages with vastly friendlier type systems and language features? Rust, D, Haskell, etc. all offer similar performance profiles and are much nicer for the programmer.
- pcwalton 10y agoYes, that's the approach Go takes.
- icholy 10y agoThat interface{} parameter makes me cringe, but it makes sense.
- spriggan3 10y agoGo 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 10y agoThis is nice, but generic functions are still generics.
- spriggan3 10y agoGo 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 10y agoNo disagreement. I was just pointing out that what you were asking for is in fact user-defined generics.
- bigdubs 10y agoAnother 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 10y ago> 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 10y agoAlso 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.
- eknkc 10y agoIt 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.
- twblalock 10y agointerface{} is the new void*. There are far better ways to handle generics in modern languages, which preserve type safety and aren't very cumbersome.
- masklinn 10y ago> interface{} is the new void*. More like Java's Object, especially since downcasts are mandatorily runtime-checked. And the results are exactly what one could have expected from the first 10 years of java (if slightly subdued as Java only had a single magical blessed buildin type) given the language is in more or less the same class.
- mseepgood 10y agoMore like C#'s "object" than Java's "Object".
- leaveyou 10y ago>interface{} is the new void* There is an important difference between interface{} and void* which makes it a lot less reckless. AFAIK interface{} contains not only a pointer to data but also a reference to the type of the data. Therefore you can cast that data safely to the original type (or use "switch" on the type). if origData, ok := data.(OriginalType); ok { /safe to use origData here*/ }
- interactiv 10y agoyep, I wrote this : https://github.com/Mparaiso/lodash-go https://github.com/Mparaiso/lodash-go which is in theory "runtime type safe" in the sense that is yields an error if types do not match , but it uses reflection which leads to a huge performance hit. The irony is that Go is a perfectly capable functional language when one opts out of Go type system. (Don't use that package, this is not idiomatic Go).
- frou_dh 10y ago> 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.
- ainar-g 10y agoI 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 10y ago>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 10y agoDon't fear. Be assured!