Hacker News new | ask | show | jobs
by arnehormann 4431 days ago
The setup needs a little boilerplate, but it's definitely possible. And it can support different sort orders after writing the boilerplate once. For those wanting to test drive it: http://play.golang.org/p/I_Vu34hUoV
3 comments

Interesting! Could you explain why []rune needs to be wrapped in a struct{Runes []rune}? Rather then just calling "type Runes []rune"?
It doesn't need to. You could also write type Runes []rune but the struct variant has the advantage that you can get the array back without any conversions - it's pretty cheap. And you can embed it. That's an advantage if you e.g. don't define Less on Runes but define it on RunesAsc and RunesDesc. See http://golang.org/pkg/sort/ -> Examples (SortWrapper)
The costs: allocating the memory, having it set to zero values and keeping the garbage collector a little busier. All of that more than once if you don't keep the conversions down. Profile and disassemble your program, Go comes with pretty great tools!
The Go runtime sets all memory to zero at the start of the program's execution, meaning there is no overhead for 'setting the zero values'. The amount of extra memory allocated is minimal (probably zero). Records/structs tend to be figured out at compile time so no 'extra' information needs to be stored in it. And since we are storing a pointer (a slice) the struct is already aligned so no extra storage is needed there. What it might cost is one extra level of indirection per array access, but due to the simplicity of the program, I would not be surprised if this was removed at compile time or cached (in hardware). Looking at the disassembly itself, they seem to optimize out that extra layer of indirection as well (for the most part in Swap, Len, and Less).

The real cost of this is definitely the verbosity for something that could be much simpler.

What cost do conversions incur?
You can do it that way too, http://play.golang.org/p/gsq8PCcDpx
yep, so the point of that example was that there isn't a sort.Runes() convenience method, and you have to roll your own (like with any custom type). which is a mild problem to be certain, but there are lots of other little corner cases like this.
I believe that's a good thing - I prefer a small api surface to a large one and I don't want to spend time digging through never ending functions to locate what I have to use.

For me, next to everything from Microsoft is an example for a horrible api, the one from Javas standard library is rather meh and Go is pretty much the greatest thing since bread came sliced.

"It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." —Alan Perlis

Note that I have no idea what a Rune is. But, you should check out Clojure's api. Here's a cheatsheet: http://clojure.org/cheatsheet

See also: http://stackoverflow.com/questions/6016271/why-is-it-better-...

BTW, I'd bet it takes longer to write a sort function than it does to search through api documentation and find one.

so what this is getting at more is that lambdas are a critical part of a language; the "genericness" they provide keeps you from having to write a sort method for each of your types.

instead of three separate functions for len, swap and less, you'd just have one function

collection.sort(a => a.foo)

the swap and len functions are part of the collection type. the less function would be part of an interface on whatever type foo is.

it's not so much about api verbosity as not having to write the same functions over and over.

it's possible from a pure performance perspective that setting up the closures is bad but it's something i'd be willing to take for that much less code to write.

You don't even need a stuct ...

http://play.golang.org/p/GHzsNdtiNf