Of these, caring about the fact that it is procedural seems pure opinion. Lacking a package manager is not really a language issue (PHP's package manager, for example, is not coupled to the core language).
So, we are left with the lack of generics and the lack of expressivity. I'm not deep enough in the weeds to be able to argue pro/con for generics intelligently right now, so I will concede that as a concern that has been raised by many.
The lack of expressivity seems to be an inexorable consequence of the goal of simplicity, so I'm sympathetic. That said, it seems to be a tradeoff acknowledged by Go's authors, not an oversight.
Overall, these points don't convince me of the author's thesis (or, at least, they don't seem to justify the title's degree of inflammation).
He is.
Whatever his motivations, he created a very productive language. As it turns out, even advanced programmers benefit from having a simple language when it comes to getting practical work done.
I read the Pike quote very differently. When Pike says: "The key point here is our programmers are Googlers, they’re not researchers." I thought he meant programmers today use google to assist them in programming.
News flash! Not everyone is a brilliant developer. And that's okay!
News flash! Not ever developer has extensive programming experience and can pick up new concepts quickly. And that's okay!
Go is too simple for you? Drink a big glass of shut the hell up and go write a program in brainfuck or something.
Intelligent programmers aren't dependent on the language they use to become better developers. There is no disservice in being able to build something quickly.
I'm making this point quite tongue in cheek however...
By that logic why do programmers hate Visual Basic so much? At least VB6 was very much a "simple language" relative to other things around at the time (less so with VB.net/C#).
A lot of the arguments people are making here (less is more essentially, and clear syntax wins over complexity even at the cost of efficiency) then VB6 should be something we're modelling modern languages off of, but it is not...
PS - Remember I am not being literal here. VB6 had some issues both then and now. I am not really comparing Go to VB6, I am comparing the arguments made in support of Go to arguments that could be made in support of VB6.
Which makes Go a great option.... if you use it properly. It means you don't need to worry about a programmers language history when you hire even if you need them to be productive right away.
It means you can hire the smartest developers, regardless of whether they have been doing embedded work, or spas in js, or large enterprise application dev in java, etc.
I definitely think the too-simple nature of Java is the reason behind all the reams of boilerplate Java code found in most any Java project, and I can't see how Go would be any different. It seems like a shame not to have learned that lesson.
Nobody is coding the sum of a list of integers for all the various integer types. People more likely use custom types anyway, and only have to create operations on those custom types ( except maybe for go language designers themselves). So there's always a suspicion that somehow there should be a way to code something clean using interfaces only.
Also, I wasn't impressed by the speed. I wrote a program in Ruby, Go and Elixir and expected Go to win, but is was 1x, 5x, 20x respectively, and I could never figure out why there was such a discrepancy.
Even so, if they added generics and improved performance, I would be very inclined to use it. It is surprisingly comfortable to code in.
"Lacking a package manager isn't a language issue, this language that's nearly universally derided doesn't have one."
I see what you're saying, but that strikes me as a really bad example. That being said, it is strange to me that a modern language wouldn't have any reasonable story around package management. The argument I've most commonly heard is that applications should be very small bits of functionality, thus making a full-blown package manager unnecessary...sure, that seems reasonable...except dependency management is still (aside from the whole generics flame war) one of the most common complaints I've heard from Go devs.
To be honest, I don't understand all the vitriol. That's by far the most bizarre thing about Go to me.
Simplicity is a good thing. It's a virtue. It's part of what made UNIX a success. It's not something to shun or avoid.
Adding features adds complexity and complexity is not free.
Notice how the industry still has't jumped ship whole-sale to Haskell?
* the author (and everyone else who complains about Go) simply hasn't made any appreciable investment in learning Go
* the language itself doesn't naturally lend itself to most programmers easily finding the most succinct/powerful expressions available, instead providing a grain that favors clarity over other values
* the documentation and tutorials available don't teach programmers how to write succinct and expressive Go
If Haskell's succinctness level is 1, then I would rate python's at 2, go's at 4, and java's at 20.
If D and C++ programmers hate Go, it's doing something right.
I think that can be said of pretty much all programming languages.
Part of the reason Go is so popular is because we place such a low value on education, training, and long term productivity, and a high value on getting things done quickly. In general our industry is focused on the short term, is fad driven, and is more than willing to turn on our own.
Go is a language created to win in this kind of environment. And because people hate the environment... they focus their animosity on the tools that are successful in our environment.
Simplicity is deceivingly challenging, and quite different from simple-mindedness, which seems to be what the author is accusing Go of being.
Keeping code simple, elegant, and consistent is IMHO one of the most valuable principles a team can adhere to. Simple is not necessarily shorter, as short can often be subtle and sneaky rather than simple. Complex power tools can be fun to the inquiring mind, but the ultimate consumers of your product almost never appreciate how you built it, but almost always appreciate the final outcome.
A wise man once said: “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian Kernighan
One place this shows up: Build times. Turning a 45-minute build into a 10-second build, times 30 programmers, times several builds a day for 10 years... that adds up to a really big difference.
Of course, the problem is that for the compiler implementation, those traits are completely reversed (adding generics at this point is like hitting the compiler with a mallet); and that happens to be Go's primary excuse for lack of generics/templating/macros/anything sane. I think dev ease-of-use matters a lot more than core dev ease-of-use though. Even if the compiler must grow in complexity and average compile time, the benefits to devs are worth it.
In that light, the actual usage statistics are probably a better metric of the language's success than the +/- ratio on hacker news.
Highly readable code helps reduce bugs. But if that code is also so simplistic that it necessitates a lot of verbosity, you definitely increase the chance of introducing some stupid bug. Thankfully, as a compiled language, Go can find a decent portion of the silly stupid bugs where in a more expressive language like Python they might go hidden for longer, but it's still a big tradeoff you're making.
People developing whole applications use custom types. People developing libraries meant for general use seem to prefer not limiting their stuff to working with their language's comparatively few built-in types (at least, that's how things seem to go in languages with generics -- Guava's BloomFilter should work with any type, even if that type was created well after Guava was written).
So that's why i'd like to see real-world problems that illustrate some concrete examples.
"the methods of these interfaces have different names. Object functions have a method named apply, where methods returning numeric primitives have method name applyAsInt, applyAsLong, or applyAsDouble. Functions returning boolean have a method called test, and suppliers have methods called get, or getAsInt, getAsLong, getAsDouble, or getAsBoolean."
The solution that go offers for such problems seems to be to deny that there is such a thing as libraries and to promise to deliver migration scripts whenever changes in the language or its libraries break existing programs.
That approach works fine now, but I am not sure it scales to a situation where go is truly successful; in particular, I think go, at some time, will have to allow for dynamic linking to support commercial libraries, if it wants to become truly successful.
On the other hand, the times of copy protection on software being normal are far behind us, and CLR has an ecosystem for commercial libraries, that decompile so well that CLR libraries do not differ much source code. Maybe, I am underestimating the willingness of commercial vendors to start shipping libraries in source form.
Would you say that Go is not excessively verbose in non-trivial use cases ? I recently had to sort a struct list in a program. Added lines of code for sorting a single list once : 30. What the ...
It seriously depends what you're doing. As someone put Haskell recently "all the possibilities of advanced algebra combined with all the clarity of advanced algebra".
Simplicity is only a real success if it doesn't throw out the baby with the bathwater.
> Adding features adds complexity and complexity is not free.
And taking away features is free ? Why aren't you programming in LISP then ?
Yes, if you want to generalize code to release a library to a much wider audience, you'll either end up writing quite a bit of duplicate code, using the code generation tools, or diving into the "reflect" package (which would let you write Sum in one method).
That said, I've never had to do either of these in writing about 10k lines of Go code.
[1] http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design
>Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it.
Not hard as in "can't do it", but hard as in too hard to implement without adding the ever feared "complexity".
For the record, I like Go and its philosophy, but I think, above all other issues with the language, the lack of generics is a huge weakness and will eventually be looked back on as a mistake. Not just for not having them before 1.0, but also for waiting as long as they did for adding them, assuming they ever do add them.
Ok, Go is not object oriented, but it has a few features that make it possible to do some stuff that are very cumbersome if not impossible in C.
- first class functions and closures
- you can safely take an address of a local variable and use it after the function's scope exits (the compiler takes care about promoting variables to the heap)
- interfaces allow you write modular code: e.g. you can create your own Reader and Writer interfaces and the standard library can operate on it. People are focusing much about generics/templates but it's not that Go completely lack any way of creating modular and reusable code.
- pointer/value distinction but having safe pointers by disallowing pointer arithmetics and instead providing runtime bound checking (slices)
- garbage collection (this topic actually opens a can of worms of it's own, regarding the placement of the language on the spectrum)
If you take C and add those features (instead of starting from another language and removing the features, see Blub Paradox) it's more apparent that it adds some value.
One could argue that the comparison with C misses the point, given that one of the main reasons C is still alive and kicking is because of it's ubiquity and the fact that its calling convention is the de facto standard of modern operating systems, all of which is defeated by introducing a new language (with a non-C calling convention!) that doesn't even aim at the level of control (especially over memory allocation) that C gives.
However that's where Go's cultural roots are. Well, except for the concurrency parts and other bits that were inspired from other languages, but when talking about sorting or reducing arrays, that part stems from the C culture.
I have the feeling that one of the reasons Go is so successful, is that there are many people who would actually like C but recognise what a giant time sink can be to become proficient and write good quality software in it.
1) go has generic functions : http://golang.org/pkg/builtin/, they're just not accessible to you
2) go has generic types : slices, maps, and channels, all of which have slightly differing behaviour, including some highly counter intuitive and contradictory behaviour (example: slices are pass-by-reference, arrays are pass-by-value. In other words []int and [5]int behave entirely differently)
3) go has overloaded functions : http://golang.org/pkg/builtin/, they're just not accessible to you
4) go has exceptions (panic/recover), negating all the advantages of Go error checking, and providing zero fixes for the problems it introduces (finding the source line where an error happened and if/how multiple errors are related. Easy in Java/C++/..., hard in Go) (in C++ you have to be aware of whether any external code you use throws exceptions ... in Go you have to be aware if any external code you use panics. And if you say I haven't dealt with it, that means that you quite literally haven't dealt with it. Same as in C++. External libraries throwing exceptions is perfectly fine ... as long as they never actually throw an exception. Panicing standard library is fine ... as long as it doesn't panic ... If you're looking for correct code, it is of course not fine)
5) Go's "simple" threading and panics. Try crashing a Go program with shared data with a null-pointer derefence in the shared data. Someone please explain to me how the resulting output is simple.
6) golang's own compiler and standard library are not in fact idiomatic Go. This goes from small problems (like total lack of unit tests in quite a few places), to larger ones, like not using interfaces for logging.
7) interface{}. I just grepped a reasonable, thoroughly reviewed codebase I've written, of several tens of thousands lines of Go. Result: 2.7 uses of interface{} per 1000 lines of code.
Is this what people here call simple to think about code ? I would argue that you don't understand a codebase until you've read it. That's a certainty. So can we at least agree there's a point where verbosity no longer increases readability ? I hope you can see Go is far past that point.
Go's type system : riddled with exceptional behaviour. Literally it says "type system applies unless it's doing <-, cap, len, copy, new, append or delete calls", in which case we do something custom. The resulting behaviour, of course, is inconsistent with Go's type system (which is really the point of the code of course, unfortunately, there's surprises buried in there, and those calls are inconsistent with eachother as well).
All of these are implemented as exceptions in the compiler. I would warn you about this link : once it is seen, it cannot be unseen :
https://github.com/golang/go/blob/master/src/cmd/internal/gc...
The irritating part is that this sums up Go mailinglist behaviour quite well. Coding practices is for you, not for us, the Go authors. Generics ? Of course we need that, but you obviously don't as you're a bad programmer. And if you're asking for something else that must mean you suck. Overloading ? Ditto. Generic types ? Yes for us, not for you though !
Of course, all of these claims are thrown around and when you actually read the compiler code you wonder ... do these guys know about type systems ? Don't these guys know about the standard coloring algorithm ? Why aren't they using extremely-well-known algorithm X for this ?
In other words, it really looks like the compiler was (and is) written by someone who last opened a compiler book in the 70s. But reading the mailinglist, you'd think they were the central authority on compiler theory and you're stupid. This is in fact not the case.
Go works and feels like a late-90s language like Oberon. Clean at the surface, with lots of buried ugliness. Lots of weird custom datatypes, forms and parts of the standard library that are not implemented in the language itself. It's why I switched to C/C++. Go is simply the same as those old languages we moved away from. There is nothing in Go that cannot be achieved better and more flexible in C++, D and Rust.
You can use the standard library sort methods by making your type implement the sort interface. Heres an example taken from the example in the sort docs: https://play.golang.org/p/oeRIhHi1Ei
The only place go is more verbose is sorting, and lack of map, filter, and list comprehension. Most of the latter just means you need a 3 line loop where you have one line in python. But that should not be a great effect on any reasonable size program.
Rust, for how perfect it really is, treats developers as humans. You must be smart if you can use it - but it doesn't trust you to have any idea what's really going on when a program gets large. This is a good thing IMO.
Honestly, anyone who thinks Rust is trash is just wrong. I can get the argument that there just will never be enough people who can use Rust but having learned Go and then Rust - I have to say Rust is the most well designed programming language ever. I can't believe what's in it and it's far and away the most advanced programming language ever. It's hard to compile but when it does you have a good chance it's right.
fileBytes, _ := ioutil.ReadAll(<file>)
text := string(bytes.Join(bytes.Split(fileBytes, '\n')))
fmt.Println(text)
> Added lines of code for sorting a single list once : 30. What the ...Sorting requires implementing three methods, at least one of which is usually given to you for free (Len). A simple case will usually cost about 9 lines of neatly formatted code, 3 if you're not so neat (which the Go sort library does itself).
func (sl structSlice) Len() int { return len(sl) }
func (sl structSlice) Less(i, j int) bool { return sl[i].MyKey < sl[j].MyKey }
func (sl structSlice) Swap(i, j int) { return sl[i], sl[j] = sl[j], sl[i] }
Ultimately, even this isn't a case of verbosity so much as it is not abstracting away the basic sorting functions.If you are a good Haskell/D/Lisp developer then switching to Go will probably halve your productivity over the long term.
There are a lot of benefits to using Go but lets not pretend there aren't any downsides.
However, one thing I'll say is that it's a big problem for people like me if a language requires you to be smart to use it. It's really, really hard to hire only smart/experienced developers.
What I need, and what I hope Rust can be, is a language that is opinionated (in the right ways) and won't compile if an inexperienced dev tries to do something dumb.
In Rust, the fact that variables are immutable by default (but can be explicitly declared mutable) is the kind of thing I'm talking about.
Yes, I know the Go authors do it too. And of course we know the answer : they're ashamed of just how bad it is, and mask it by making exceptions in the style guide for this specific case. You also left out the type declaration and the actual sorting call. Here's the full code :
type myStructSlice []struct
func (ms myStructSlice) Len() int {
return len(ms)
}
func (sl myStructSlice) Less(i, j int) bool {
return sl[i].MyKey < sl[j].MyKey
}
func (sl myStructSlice) Swap(i, j int) {
return sl[i], sl[j] = sl[j], sl[i]
}
...
sort.Sort(myStructSlice(sl))
And for this trivial example we're at 15 lines of (properly indented) code. You also have polluted the name space with one-use names for types. Is it really so hard to believe that this easily explodes to 30 lines of code for real life examples ? The Less function is not going to be nearly as simple in real life struct examples (natural sort + field precedence).Compare to the same code in Java:
Collections.sort(theList, (SomeType s1, SomeType p2) -> p1.field.compareTo(p2.field));
D: sort!("a.field < b.field")(theList)
C++: thelist.sort([](const someType& a, const someType& b) { return a.field < b.field; });
So Golang is 5x more verbose than Java in this instance. This a particularly bad example, but that Golang is actually more verbose than Java is not an exception in my experience.Without access to list/dict/set comprehensions, or libraries like itertools, or a lightweight lambda syntax or something like Ruby's blocks, transformations on collections will always be considerably more tedious and verbose.
Various functions have "bring-your-own-buffer" calling conventions, which will often double or triple the number of lines required for those function calls.
No tuple unpacking, no ability for functional programming (Python's isn't that amazing but with functools and some of the builtins, you can get pretty far), no operators for string formatting or anything but absolute barebones operations.
Combine that with what Go lacks even compared to languages like Java (no inheritance [which is usually an anti-pattern but does decrease verbosity when used properly], no generics, no deep type/class reflection) and it's hard to say that Go isn't a verbose language.
No statically typed language is going to be as terse or expressive as Python can be.
I admit I'm not an expert in programming language design though, so I may be completely wrong about both Java and Go.
As you would imagine, doing this is quite hard, and quite inconsistent from project to project. Lines of code may bear some correlation to future bugs in code for some projects and languages, but it's far from clear cut that more lines of code == more bugs or more complexity.
You would need to know the nature of the tasks to pick out those that need longer answers but all the Go tasks are here: http://rosettacode.org/wiki/Category:Go - most of which should have Python solutions.
Serious question. I don't know the PHP community at all.
So, yes, it was exceedingly obvious that the author had not made any appreciable investment in learning the language.
This "they laughed at Einstein, so I must be right too" mentality is pure fanboyism.
Lots of C++ "features" on banned on major projects because of complexity and build time issues -- templates, exceptions, operator overloading...
Go is 185175% better than Java and 8165% better than Haskell -- or making up numbers just makes us all look like goddamn idiots.
Go will continue to grow at the insane pace it has because it hit a sweet spot and cared about standard library and documentation. You will continue to see high profile successes because it doesn't try to be fancy, it tries to get out of your way so you can do that job of actually transforming data. So you can be a programmer and it can be a language, not a hobby.
I am a language geek, I write DSLs on a regular basis for fun -- and I love any language that is DSL friendly -- but for actually getting my day to day "must ship", "must work", "must scale" work done -- Go to the rescue. Great docs, easy to train people on, ultra-simple spec, multiple compilers, easy enough to integrate C code, and a really great vibrant community.
Also, static binaries -- so the DevOps guys don't hit you with sticks.
I still remember the first go program README.md I shipped. "Umm, get foo to box, ./foo in a way so that it runs persistently and at startup."
Easy way to get your apps to the front of the line in the deploy queue -- all the time.
This "it's so simple!" nonsense is an exemplification of that.
By reducing everyone (even good programmers) to the lowest common denominator, talent is far more commoditized and pluggable. You can throw away Programmer A because Programmer B is "as good as it can get for
How will you keep your code simple if your procedural bent causes you to create dependencies/coupling at will?
How will you keep your code simple if your variables are mutable?
Recipe for complexity and bug hell
No one should be using mysql_* anything; no one should have been using it for years. It's deprecated. It throws warnings when run. PHP's love of forced backward compatibility causes some very interesting things to be remained.
Paamayim Nekudotayim isn't called that anymore and hasn't for a long time.
The author raises issues about things like @fopen(url) - no one I know, or myself, has ever done that. It makes absolutely no sense to.
PHP has autoloading/"modules"/dependency injection/a proper package manager/etc (article is from early 2012: composer was largely popularised from what I can see a bit after that).
The author complains about no stack traces - sure, there won't be any on a single file bad function name, but any time I've used a proper request library or anything best practice, I've gotten a proper stack trace with file names, lines, etc.
--
There are a lot of somewhat odd complaints or wildly strange, like "No Unicode support" and "PHP is naturally tied to Apache. Running it separately, or with any other webserver, requires just as much mucking around" which makes absolutely no sense to me. The author of this article even says that if you want to run two versions of PHP, you rebuild Apache? That's absurd.
> 'The “bunch of files” approach, besides making routing a huge pain in the ass, also means you have to carefully whitelist or blacklist what stuff is actually available, because your URL hierarchy is also your entire code tree'
None of this makes sense either: unless you are doing some seriously outdated horrors, you have effectively one /index.php router and a public asset folder for the webroot.
Having to tell the standard library how to swap data in a slice and to obtain a slices length is simple... why doesn't the standard library know how to work with basic types? This way I don't end up writing by accident:
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[j] }
For example, Go is praised for being a simple language that everyone can learn quickly, yet when someone shows what they picked up "that isn't how you do it."
I get that it is one thing to get something done, and another to learn an idiomatic approach. But when the sort package is hailed as the example for both why Go doesn't need generics and Go does need generics, I think it is safe to say that even the language creators don't know how to use Go.
>Over the course of the past few months I’ve been using Go to implement a proof of concept program in my spare time.
It's almost as if, like most people who post on Hacker News, you took a cursory look at the title, wrote some inane comment that supported your point, and squeezed out a reply.
we decided to transliterate our 90k lines of Python directly to Go, line by line
The 90K number includes our tests, but without tests, the Python codebase is 36,784 lines of code. Those same lines of code became 41,717 lines of Go code. So, not that much of an increase. When you consider that's just 4,933 more lines, it's not crazy to assume most of those are closing braces.
I'd say closing braces and trivial expansions of list comprehensions into 3-5 line loops.
Implicitly fulfilled interfaces make it trivial to decouple code, because I can pass a type to a function in a different package, and that package doesn't even need to know that type exists.
You're obviously pushing the pure functional route, which is nice, but 95% of code in production is procedural. There's a reason for that. I could speculate why, but I don't need to.
an example from https://www.spacemonkey.com/blog/posts/go-space-monkey -
we decided to transliterate our 90k lines of Python directly to Go, line by line
The 90K number includes our tests, but without tests, the Python codebase is 36,784 lines of code. Those same lines of code became 41,717 lines of Go code. So, not that much of an increase. When you consider that's just 4,933 more lines, it's not crazy to assume most of those are closing braces.
I'd say closing braces and trivial expansions of list comprehensions into 3-5 line loops.
There's a real life example of direct transliteration, not just a rewrite. That's 13.4% more lines. I think that's pretty close.
I will. There's a pattern out there and it goes something like this:
1) Most programming classes still teach procedural
2) New, typical real-world programmer looks at procedural and functional, finds functional more alien and difficult (because it's far more dissimilar to the popular languages s/he played around with in their youth), settles on procedural
3) 10 years later, after spinning a significant percent of wasted cycles on piles of procedural spaghetti code and spending hours debugging classes of bugs that ended up coming down to a lack of managing complexity, various interdependencies, no recognized schedule to pay down difficult-to-quantify technical debt, and mutability... programmer looks at functional languages again and finds them not lacking
4) programmer takes on a side project in a functional language, thinks it's awesome, mind is bent in pleasant shapes, considers quitting day job or "the big rewrite", realizes the latter is not feasible (see: Joel Spolsky), gets frustrated with the status quo
5) programmer posts to future incarnation of Hacker News probably sounding like an ivory-tower prophet, preaches about macros and homoiconicity and immutability and the dynamics of programming teams, ends up angel-investing and founding an incubator instead of fighting the hopeless procedural-vs.-functional battle
6) Repeat.
;)
EDIT: BIAS: I think Elixir (http://elixir-lang.org/) finally has a real shot at breaking this cycle. It's the first functional language I've used that "felt" accessible enough to most folks (Ruby-ish syntax) AND has all the typical functional niceties AND has real macros without being jarringly off-puttingly homoiconic AND has an extreme focus on concurrency (perfect for the future Web... it can fire off a million PID's in a second) AND it embraces failure (good for anything that touches "the real world") AND uses the Actor model (a candidate for "most scalable language design pattern"). OO is, IMHO, dead man walking right now. It's too easy to pass mutable state around everywhere, it complexifies code too much by allowing any code anywhere with an instance of a class to call methods on it (therefore coupling the class implementation to the entire codebase), it doesn't realize the cost of inheritance, it is difficult to parallelize, etc. etc.
But how about things like:
g = some_input() # A list with 3 elements
a, b, c = g
Or in Python 3+: lst = [1, 2, 3, 4]
head, *tail = lst # 1, [2, 3, 4]
*init, last = lst # [1, 2, 3], 4
a, *b, c = lst # 1, [2, 3], 4
"Generics" is not a feature, its a bugfix. It refers to the type checker not rejecting perfectly fine code. In practice, you can just read 'generics' as 'this product does not contain asbestos', or "the mandatory type checker does not reject perfectly fine code".
Type systems are supposed to help you catch bugs at an earlier stage than run-time execution. However, implementing a type system is very hard and academic in nature, and the type of people who are good at making production ready high performance compilers generally aren't very good at type checkers. This is why many languages initially launch with a broken type system (and often a broken garbage collector), but eventually patch things up.
The problem Go has, is that its main author makes such cringe-worthy statements about generics, that we now have a large group of enthusiastic people who, on the basis of authority of the author, exclaim equally confusing remarks. Everything got so defensive that this typical launch bug, normally fixed with a release or two, is now part of the culture and DNA of this particular ecosystem. The sad thing is, these are all talented people, that instead of impressing us with their awesome skills, are embarrassing themselves in front of anybody who ever read anything about category theory.
For example, here's a "generic" algorithm to fold the (+) operator in Javascript:
function( xs ){ var result = 0; for( var i=0; i<xs.length; i++ ) result = result + xs[i]; return result }
No type checker, no fuzz. There is nothing complicated here.
But if you translate this to Go, you would you would need to copy this code over and over again for every potential leaf type you want to use this algorithm with and change only the type signature. The complexity is actually the result of a mandatory type checker that is broken by design. The most simple solution to support 'generics' would be to make the type signature optional. g := some_input() // A list with 3 elements
a, b, c := g[0], g[1], g[2]
I'll grant you, having to specify the indices is slightly more verbose, but it's also a lot more clear... because what happens when g has more or less than 3 elements? In Go it's clear, more is ok, less will get you a panic. lst := []int{1, 2, 3, 4}
head, tail := lst[0], lst[1:]
init, last := lst[:len(lst)-1], lst[len(lst)-1]
a, b, c := lst[0], lst[1:3], lst[4]
Again, I don't think the magic unpacking is really helping that much... doing it the same way you'd do anything else in Go is slightly more verbose, but it's also not some new syntax you have to figure out either.One of the reasons it's not widely adopted is that the features that programmers take for granted, like built-in syntax for mutable variables, are missing, i.e. it's too simple.