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
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.
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.
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.
Go has nothing new. Go has nothing special. You've see all of Go before. You're right. I get it. But what you haven't seen is all these things together in a single language. Where they all come together to make a really damn useful core.
You've used channels before, cool. You've used the pure bliss that is the slices efficiency in a couple of other places and grew to expect the behaviour in new languages. You're proficient with threads, coroutines, actors, futures and promises. You've quacked and walked and talked like a duck. But you've never (probably) done all these things together. And that's what Go is. Go is all the things that we've always known are good, smushed together. Go tries to remove all the things that are bad about languages and erases the majority of it (or at least does a good try to give you a decent alternative).
Static typing, with all it's greatness, can make for some damn verbose code. You sit and type at the compiler what each and every variable is, you painstainkingly explain (to a computer) explicitly what each part accepts and returns. It's annoying, and mostly avoidable. There are several basic types which have literal syntax, or functions which create those types. Or special syntax. So why do we need to use the special syntax to create those types along with telling the compiler which type it is? We don't. Type inference. Go has a kind of type inference operator (:=) which will deduce the type at compile time and save you precious keystrokes. This isn't anything new, tonnes of languages do it.
Useful but light object oriented programming. There are tonnes of C++ style languages which make classes seem like the final boss of programming. Where all yours types have to be carefully categorized and laid out in neat little ways in order to create a taxinomal tapestry, a kind of zoological museum of each working object in your code. It's weird the kind of gradiose ceremony we give to the simple act of giving stuff... stuff to do . Nouns are things, nouns do verbs. That's simple as that. There should be nothing special about that style of programming. It allows certain gains. It has wonderful encapsulation of methods which operate on the same data (verbs acting on parts of the noun), it has a nice semantic use (x is a y) but it certainly doesn't have a use everywhere. Hell, I've been writing a lot of backend stuff for the web and I've not written a Python class in about... 3 months. Many languages bring OOP back down to the level of "just another paradigm", where it should be. This is nothing new.
Concurrency is a first-class citizen. This is awesome. No longer do I have to search through the standard library only to be met with an aging, creaking model which doesn't quite fit my needs. Nor do I have to use the same tired methods for making my applications concurrent. With annoying models like threads and joins and crufty things like that. Go just goes. I ask for a concurrent routine, I get a damn concurrent routine. It makes concurrency feel solved for a lowly programmer like myself. This is nothing new.
I guess my point is that, whilst on paper (and I felt like this myself) that Go may look like nothing new. Where it looks like you could get those features elsewhere and not have to care about learning yet another new-school language. You've not had them all together. Or at least this baked-in to the language.
I had to hack the CSS a bit to make it readable, but I agree with the author. Particularly, I like his comments on Go's attitude towards OOP.
As a Ruby hacker, I find that everyone on my team really likes to build a class and think of the instances as real physical objects. That's to be expected because it's how we were all taught to think of classes/objects/OOP in general. Objects in your code are not physical objects. You don't have to carry them around with you and pass them back and forth and up and down. You can build new objects that are specific to your functions.
I find that Go encourages me to build structures that are relevant to the situation instead of classes that are broadly scoped concepts. I also feel this way when I work with C, but I like it better in Go due to the receiver syntax.
It's true that my problems in my Ruby apps are my own (and my team's) damn fault. We should be better at single responsibility. Still, Go's approach to OOP encourages single responsibility and other good practices. I don't understand what's boring about that. I for one get a real thrill when I write some Go code then go over it and think "damn, that's just not going to break..."
It has a mediocre type system, bad support for genericism, too much reliance on non-extensible language keywords (range, make, etc.). Want to range over a tree? Too bad. Or maybe wrap the tree with a chan and watch performance and simplicity go out the window.
I mean, come on, what modern language actually recommends casting to the top type? That would be like if idiomatic C++ involved casting things to void*, or if idiomatic java involved casting things to Object, just so you can write generic functions and types.
I like Go for some stuff, but yes, it's pretty restricted. Even for the design goals that are lauded (simplicity, being boring as a virtue, fast compilation speed, no magic, concurrency built-in etc), they could have achieved them with a little more flair.
One could say that if we compare the team that worked on C and Plan 9 to the Rolling Stones, Go is like their nineties albums.
I think you are evaluating 'go' based on feature set rather than the amount of friction a developer experience when using it to develop a good product.
C++ is fantastic but I personally experience far less friction when working with 'go' for most of my task.
Of course, not all nouns "do verbs", which is why we end up with warped associations between particular language utilities, like classes, with notions from one philosophy taken to weird limits.
Circles and Ellipses, for example, don't do anything. They're data structures. They're nouns, but they have no functionality. They have no verbs. The correct solution to the Circle-Ellipse problem, the most famous demonstration of one flaw with OOP, can be expressed elegantly and correctly, in C++ and other "C++ style languages", using classes. Doing so doesn't make anything object oriented, and we shouldn't associate giving things names with a requirement for any particular set of associated verbs.
All language features are tools, and while I'm not saying Go is an inferior tool if you're satisfied, we shouldn't make blunt instruments, or carry fewer tools, just because some people don't know what they're doing. I'm currently not satisfied with the set of features Go provides... but then I also want to see some Go features in C++. Let's not get hung up on it.
27 comments
[ 3.1 ms ] story [ 72.6 ms ] threadAn example; try to sort a slice of runes.
Also couldn't load the page.
The real cost of this is definitely the verbosity for something that could be much simpler.
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.
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.
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.
http://play.golang.org/p/GHzsNdtiNf
Go is boring
Go has nothing new. Go has nothing special. You've see all of Go before. You're right. I get it. But what you haven't seen is all these things together in a single language. Where they all come together to make a really damn useful core.
You've used channels before, cool. You've used the pure bliss that is the slices efficiency in a couple of other places and grew to expect the behaviour in new languages. You're proficient with threads, coroutines, actors, futures and promises. You've quacked and walked and talked like a duck. But you've never (probably) done all these things together. And that's what Go is. Go is all the things that we've always known are good, smushed together. Go tries to remove all the things that are bad about languages and erases the majority of it (or at least does a good try to give you a decent alternative).
Static typing, with all it's greatness, can make for some damn verbose code. You sit and type at the compiler what each and every variable is, you painstainkingly explain (to a computer) explicitly what each part accepts and returns. It's annoying, and mostly avoidable. There are several basic types which have literal syntax, or functions which create those types. Or special syntax. So why do we need to use the special syntax to create those types along with telling the compiler which type it is? We don't. Type inference. Go has a kind of type inference operator (:=) which will deduce the type at compile time and save you precious keystrokes. This isn't anything new, tonnes of languages do it.
Useful but light object oriented programming. There are tonnes of C++ style languages which make classes seem like the final boss of programming. Where all yours types have to be carefully categorized and laid out in neat little ways in order to create a taxinomal tapestry, a kind of zoological museum of each working object in your code. It's weird the kind of gradiose ceremony we give to the simple act of giving stuff... stuff to do . Nouns are things, nouns do verbs. That's simple as that. There should be nothing special about that style of programming. It allows certain gains. It has wonderful encapsulation of methods which operate on the same data (verbs acting on parts of the noun), it has a nice semantic use (x is a y) but it certainly doesn't have a use everywhere. Hell, I've been writing a lot of backend stuff for the web and I've not written a Python class in about... 3 months. Many languages bring OOP back down to the level of "just another paradigm", where it should be. This is nothing new.
Concurrency is a first-class citizen. This is awesome. No longer do I have to search through the standard library only to be met with an aging, creaking model which doesn't quite fit my needs. Nor do I have to use the same tired methods for making my applications concurrent. With annoying models like threads and joins and crufty things like that. Go just goes. I ask for a concurrent routine, I get a damn concurrent routine. It makes concurrency feel solved for a lowly programmer like myself. This is nothing new.
I guess my point is that, whilst on paper (and I felt like this myself) that Go may look like nothing new. Where it looks like you could get those features elsewhere and not have to care about learning yet another new-school language. You've not had them all together. Or at least this baked-in to the language.
As a Ruby hacker, I find that everyone on my team really likes to build a class and think of the instances as real physical objects. That's to be expected because it's how we were all taught to think of classes/objects/OOP in general. Objects in your code are not physical objects. You don't have to carry them around with you and pass them back and forth and up and down. You can build new objects that are specific to your functions.
I find that Go encourages me to build structures that are relevant to the situation instead of classes that are broadly scoped concepts. I also feel this way when I work with C, but I like it better in Go due to the receiver syntax.
It's true that my problems in my Ruby apps are my own (and my team's) damn fault. We should be better at single responsibility. Still, Go's approach to OOP encourages single responsibility and other good practices. I don't understand what's boring about that. I for one get a real thrill when I write some Go code then go over it and think "damn, that's just not going to break..."
It has a mediocre type system, bad support for genericism, too much reliance on non-extensible language keywords (range, make, etc.). Want to range over a tree? Too bad. Or maybe wrap the tree with a chan and watch performance and simplicity go out the window.
I mean, come on, what modern language actually recommends casting to the top type? That would be like if idiomatic C++ involved casting things to void*, or if idiomatic java involved casting things to Object, just so you can write generic functions and types.
One could say that if we compare the team that worked on C and Plan 9 to the Rolling Stones, Go is like their nineties albums.
1 Is it joyful to write without too much cognitive load? 2 Is it getting things done?
Go fits both for them.
C++ is fantastic but I personally experience far less friction when working with 'go' for most of my task.
Of course, not all nouns "do verbs", which is why we end up with warped associations between particular language utilities, like classes, with notions from one philosophy taken to weird limits.
Circles and Ellipses, for example, don't do anything. They're data structures. They're nouns, but they have no functionality. They have no verbs. The correct solution to the Circle-Ellipse problem, the most famous demonstration of one flaw with OOP, can be expressed elegantly and correctly, in C++ and other "C++ style languages", using classes. Doing so doesn't make anything object oriented, and we shouldn't associate giving things names with a requirement for any particular set of associated verbs.
All language features are tools, and while I'm not saying Go is an inferior tool if you're satisfied, we shouldn't make blunt instruments, or carry fewer tools, just because some people don't know what they're doing. I'm currently not satisfied with the set of features Go provides... but then I also want to see some Go features in C++. Let's not get hung up on it.