Hacker Newsnew | comments | show | ask | jobs | submit login
Another go at Go failed (oneofmanyworlds.blogspot.com)
225 points by scapbi 474 days ago | 267 comments



I think there is more to learn here about engineering mistakes than about Go:

- Why pick Go for this project in the first place? Those days the biggest productivity difference that arises from language choice comes from the availability of libraries, and it does not take much research to see that Go wasn't particularly targeted at numeric computing and that library support for those kinds of things is very poor. There is a number of mature platforms for this class of problems, SciPy, MatLab/Octave, C/C++ with various BLAS-derived libraries etc.

- The bit on poor performance is unconvincing because the source of the difference has not been identified. The speculations about Go and Java that follow are so poorly backed by any evidence and so wild they should have been cut out from the article. It's clear that the author has no clue what really happens in either case, and he proceeds to draw conclusions anyway. This kind of "magical" thinking about black boxes one doesn't understand is unfortunately all too common across software engineering.

- One place where I agree with the author is that Go's zoo of builtin data structures is really, really poor compared to Java. I mean compare:

http://golang.org/pkg/container/

http://docs.oracle.com/javase/tutorial/collections/interface...

http://docs.oracle.com/javase/tutorial/collections/implement...

-----


>I think there is more to learn here about engineering mistakes than about Go: Why pick Go for this project in the first place?

I hate this type of non-productive comment.

"Why he picked Go" is beside the point. That was his personal choice, and it's of no concern to us if it was a good or bad choice when he made it.

What IS of interest to us, is his findings, ie. about how (non) fitting was Go for the kind of work he describes, and for what reasons. Because that can helps us access the language ourselves for such uses.

>Those days the biggest productivity difference that arises from language choice comes from the availability of libraries

Again, not true for his needs. For what he needed, core library built-ins have sufficed in Java (Set etc). As for Go, he did find 2 libraries implementing them, but he still wished for a good core implementation.

>The bit on poor performance is unconvincing because the source of the difference has not been identified.

No, but it's well known that Go lags behind the JVM, something even the Go team aknowledges and attributes to maturity of the compiler/GC.

Plus, from the writeup, he sounds like a thoroughly decent programer to not be able to code his way out of Go performance bottlenecks. Doesn't sound like the guy who can't use a profiler (and in fact, he points in his article that he DID use one).

>This kind of "magical" thinking about black boxes one doesn't understand is unfortunately all too common across software engineering.

Random rant unrelated to TFA.

-----


This reminds me of that one guy on the go-nuts irc channel who asked for help with his Ruby port over to Go. He was scraping a set of web pages in Ruby and migrated that over to Go for its easy parallelization. His claim was that Go was 3x slower in speed. He pasted some code that seemed fine, but left out the context of what he was doing. At the end of the day, it as just an attempt to claim that Ruby is faster than Go. If he doesn't provide the entire context with benchmarks included, I'm just taking his word for it.

On another note, I built an algorithm using a bitset. At first, I used one of the libraries the author linked, but then I saw that it was easier to just do the bit-bashing myself for my particular use case. It's not that difficult if you are familiar with C and C++ programming.

If, however, you are coming over from a language like Python, Ruby, and even Java to criticize Go is an easy thing to do. Those are very high level languages that protect you from needing to understand types. The object oriented parts of Java languages give you the ability to use polymorphism, which is not as straight forward in Go. You don't have a common base class. You only have interfaces. Trying to recreate generic structures and then blame the language for not having them is foolish. If you can't program without generics, stick with Java from the beginning. Or better yet, don't do a project in Go until you understand how to approach problems the Go way.

I happen to like Go for the very reason that you don't deal with generics. Seeing the types make it easier for me to follow as opposed to following a chain of inheritance. Getting rid of all the factory code trims my code down. This makes things easier to read when you are not the author.

Comparing Java's compiler to any other compiler is going to have predictable results. Java may have the best compiler out there.

-----


Generics, inheritance, and the factory pattern are completely orthogonal features. Adding generics would not entail adding inheritance, mandating the factory pattern, or any other slippery slope feature.

-----


Most of Go's feature decisions seem to have something to do with compilation speed or how it fits in with the concurrency features and GC.

Inheritance is overrated, and the factory pattern is often overused. Both of those happen with generics.

-----


> Inheritance is overrated, and the factory pattern is often overused. Both of those happen with generics.

Generics have nothing to do with inheritance and the factory pattern. There are lots of languages that have generics but neither inheritance neither factories: SML, OCaml, Haskell, etc.

Inheritance makes generics harder, in fact, because type inference becomes undecidable in the general case.

Factories are basically a workaround for functions not being able to be freestanding (unattached to a class) in Java (the "kingdom of nouns"), a problem that Go doesn't have.

-----


Generics have nothing to do with inheritance and the factory pattern.

Where do I say such a thing? I'm saying that generics are both overrated and overused.

Factories are basically a workaround for functions not being able to be freestanding (unattached to a class) in Java (the "kingdom of nouns"), a problem that Go doesn't have.

Being the "Kingdom of Nouns" is kinda the point of Smalltalk/Objective-C style OO. (Though Alan Kay once famously said that when he thought of OO, he was not thinking of Java.) That said, while it is nice to have someplace to put functions, there are times when it's also nice not to be forced to attach them to a class. Not so sure it's a problem as much as it's just a particular approach with its advantages and drawbacks.

Where do you get that Factories are "a workaround for functions not being able to be freestanding?"

-----


>> Generics have nothing to do with inheritance and the factory pattern.

> Where do I say such a thing? I'm saying that generics are both overrated and overused.

It looks like that's what you're suggesting here:

> Inheritance is overrated, and the factory pattern is often overused. Both of those happen with generics.

---

> Where do you get that Factories are "a workaround for functions not being able to be freestanding?"

A factory is, conceptually, a function of some set of inputs that returns a new instance - which is, of course, exactly what a constructor is. Now, it's not always appropriate for a class to know every single way in which it might be assembled, so such responsibility is usually lifted out - the question is where to put it. We already have constructors, and those are functions, so it would seem reasonable that we could just write method similar to a constructor, place it in some other namespace (perhaps in a completely different package/module), and then pass that along to the component that needs to create these new instances.

For languages like Java, the problem is that functions are not first class - you can't directly pass along a method/function like (Conf -> SomeService), so instead, it's common to create some special type, like SomeServiceFactory. If, for comparison, you take a look at Scala/Haskell/C#/etc, you'll wont often spot /.*Factory/ anywhere, because a function (with the ability to close over free variables) is much more concise, and doesn't require defining new types (e.g. SomeServiceFactory, versus Function<Conf,SomeService>).

I think that, seen in this light, the practice of defining dedicated factory classes is a rather clumsy approach necessitated by the design of the underlying language.

-----


It looks like that's what you're suggesting here:

> Inheritance is overrated, and the factory pattern is often overused. Both of those happen with generics.

Non-sequitur here. To me, it's clear that I'm saying that generics are overrated and overused. Your interpretation makes no sense!

For languages like Java, the problem is that functions are not first class - you can't directly pass along a method/function like (Conf -> SomeService), so instead, it's common to create some special type, like SomeServiceFactory.

Another non-sequitur here. Factory pattern was originally popularized in the GoF book as a way of providing an opportunity for polymorphism.

If, for comparison, you take a look at Scala/Haskell/C#/etc, you'll wont often spot /.Factory/ anywhere, because a function (with the ability to close over free variables) is much more concise*

Old hand at Smalltalk here -- over 10 years. You don't often see Factory classes in Smalltalk. We also have very easy and nimble closures over variables in the context they're defined. I still don't get what you're on about.

-----


>> Inheritance is overrated, and the factory pattern is often overused. Both of those happen with generics.

> Non-sequitur here. To me, it's clear that I'm saying that generics are overrated and overused. Your interpretation makes no sense!

Ok, now I understand what you're saying. As an aside, I would suggest that most people (as is evident in this comment thread) would not interpret your statement the way you intended.

>> For languages like Java, the problem is that functions are not first class - you can't directly pass along a method/function like (Conf -> SomeService), so instead, it's common to create some special type, like SomeServiceFactory.

> Another non-sequitur here. Factory pattern was originally popularized in the GoF book as a way of providing an opportunity for polymorphism.

I agree (re: polymorphism), but I don't think that contradicts what I'm saying; functions with parametric polymorphism (with support for {co,contra,in}variance) provide the same benefits of class polymorphism in this context.

> Old hand at Smalltalk here -- over 10 years. You don't often see Factory classes in Smalltalk. We also have very easy and nimble closures over variables in the context they're defined. I still don't get what you're on about.

You're absolutely correct. However, my point was that in statically typed languages, generics are conducive to favoring closures over factories classes and inheritance. But, now I realize that we were arguing two different things.

-----


>Non-sequitur here. To me, it's clear that I'm saying that generics are overrated and overused. Your interpretation makes no sense!

You are making the non-sequitur. His interpretation is the only one that makes sense. It is not clear at all that you are saying what you claim you are saying. You are in fact not saying anything like it. You are saying two things you don't like happen with generics, but that is completely false.

-----


Okay, now you just sound like you're trolling. Please point me to the grammar rule that says my referents can't be verbs.

-----


What do you mean "now"? That was the first thing I said to you. You may wish to consider that when many people are telling you that what you said was nonsense, it may not be that all of them are crazy.

-----


What do you mean "now"? That was the first thing I said to you.

So you are trolling, and you still haven't pointed out such a rule.

-----


>Where do I say such a thing? I'm saying that generics are both overrated and overused.

How/why are they overused? How are they overrated? How can you claim there's any benefit to static typing but say generics are overrated?

-----


>Inheritance is overrated, and the factory pattern is often overused. Both of those happen with generics.

No, both of those have absolutely nothing to do with "generics".

-----


Those are all object oriented features. I was trying to compare O.O. to golang's approach.

I like the fact that you are forced to look at the algorithm vs the class hierarchy. I like that you don't have to read through factories.

I do think that generics would be great if they found a way of implementing them, however, I do not think that you need generics in order to write this kind of project.

-----


If you generate a lot of goroutines, the overhead for maintaining and scheduling them is fairly significant, particularly when compared to constructs like Python generators.

I've demonstrated this myself by comparing the goroutines example prime number generator to a similar version written using Python generators.

The python generator code was faster, but there was a hard limit to how many primes could be calculated this way; I hit the stack limit.

[Edit] Code & times: http://pastebin.com/CqkMcxdK

-----


>This reminds me of that one guy on the go-nuts irc channel who asked for help with his Ruby port over to Go. He was scraping a set of web pages in Ruby and migrated that over to Go for its easy parallelization. His claim was that Go was 3x slower in speed. He pasted some code that seemed fine, but left out the context of what he was doing.

Yes, with the exception of that being a story about some random idiot with an axe to grind, and this being a totally competent guy, that goes into detail about what he did and how, what trouble spots he found etc.

I guess, it being a hired project, he can't share the actual code. But he provided tons of pain points, well articulated.

-----


The problem is that he makes a bold statement about Go's performance without proof or at least stating what the problem in Go was.

-----


It's hard to imagine someone seriously arguing ruby is, in general, more performant than go.

I think that person was just frustrated.

-----


This notion that having a huge gaping defect is just a different way of doing things is absurd. Lacking parametric polymorphism is completely unacceptable. This is a solved problem as of 1973. There is no excuse. Inheritance has nothing to do with it, and "all the factory code" has even less to do with it. You are saying "I like go because it isn't java", which is fine, but you are implying that being java is necessary to have parametric polymorphism, which is not at all accurate.

-----


I like go because it's not object oriented. This forces me to read the implementation of the algorithm, not follow an abstraction hierarchy.

I like Java as well. It can be difficult to read the implementation when you are surrounded with classes. That was the point I was trying to make.

If you are thinking in generic containers and are programming in Go, you either chose the wrong language or need to change how you are thinking.

-----


>I like go because it's not object oriented

Lots of languages are not object oriented and still have parametic polymorphism. Like SML. In 1973.

>If you are thinking in generic containers and are programming in Go, you either chose the wrong language or need to change how you are thinking.

If you are repeating the same baseless assertion routed in ignorance, then you either chose the wrong forum, or need to change how you are thinking.

-----


... and those don't even include Java's long list of concurrent collections.

-----


Or the other Collection implementations offered by https://code.google.com/p/guava-libraries/.

-----


Or the ability to write collections in the first place, as enabled by generics. You can't even write a collection in Go unless you're dealing with interface{} or unsafe.Pointer and casting a lot.

I really like the language, enough to use it and work around the lack of generics, but that's a glaring weakness. They need some way to enable container classes.

-----


With Go, the programmer will typically not be using data structures that are concurrently accessed from multiple goroutines. It is considered more idiomatic to have one goroutine controlling a given data structure, and have the others communicate with it via channels.

-----


That is only one way of doing things. Even though channels facilitate that method, it is not unidiomatic to not use them.

Channels are a way of queueing work, which is great for many use cases.

You can use mutexes and shared memory if your situation calls for it. For example, if I am doing a graph traversal concurrently, I can use channels to send the work to many listening threads as I traverse that graph synchronously.

If for some reason, I need to update that graph's representation asynchronously, I may need to use mutexes to lock the graph since the graph is now shared memory.

-----


That approach has vastly different performance characteristics.

-----


... and the concurrent libraries of futures, fork-join, tasks

-----


Java's concurrency primitives and libraries are really overlooked in these discussions. Is the syntax too off-putting, or is it merely that Java is unfashionable?

-----


Very much unfashionable for the HN crowd. Most of the new research in concurrency is happening in Java and funded by the high performance trading industry - an industry which is very far from the HN crowd. The new Java8 stampedlock is a good example. It's possible to implement it in C++ as well, but because of the guarantees required by the lock it is a very difficult lock to integrate into C++ code. On the other hand, the JRE guarantees the correct constraints for Java code making a stampedlock very easy to use [1]. The performance of a stampedlock also seems to be the best case for any multi-reader environment. [2]

[1] http://concurrencyfreaks.blogspot.com/2013/11/stampedlocktry...

[2] http://mechanical-sympathy.blogspot.ca/2013/08/lock-based-vs...

-----


I find your claim that most new research in concurrency happens in Java strange. Perhaps you are unfamiliar with academic research in concurrency and parallelism? A way to get a small taste is to look at recent papers from the conference Practice and Principles of Parallel Programming (PPoPP).

-----


If Java is involved, it's more likely they're interested in cutting developer costs than doing any "new research." That isn't to say they aren't doing any "new research," or that the research quality is poor, or anything negative at all, really. It's just a restatement of the observation that the labor market for Java developers is quite different from C developers or C++ developers (there are a lot more of the former than of the latter--a lot more).

-----


I don't think there is anything wrong with Java as a language, but I have a question for you. Does Java's concurrency engine allow for many threads like Go or is it similar to C# in how your threads are not lightweight and are therefore limited to ixN where N is the number of CPU cores and i is a small integer < 10.

-----


The Java language specification does not define how threads are implemented.

The first set of JVMs did implement green threads, which are what goroutines are. Shortly thereafter most of them switched to red threads, aka real threads.

You can still find a few JVMs that use green threads, like Squawk.

https://java.net/projects/squawk/pages/SquawkDesign

Other than that, java.util.concurrent provides mechanisms to map multiple tasks to single OS threads.

-----


You can't spawn 80 1:1 pthreads on an 8-core machine? Huh?

Operating systems have been able to handle an order of magnitude more pthreads than that since the day pthreads were introduced.

-----


Java doesn't have a "concurrency engine", but a very large set of concurrency primitives: schedulers, locking and lock-free data structures, atomics etc.

To answer your question, yes: my own library, Quasar[1], provides lightweight threads for Java.

[1]: https://github.com/puniverse/quasar

-----


The syntax tends to be a bit verbose, that is true. Java 8 will help a bit there.

But the major problem is that many of the Java bashers tend to criticise without knowing what is possible to do in the Java ecosystem.

-----


    > Go's zoo of builtin data structures is really, really   
    > poor compared to Java.
This is a poor comparison because idiomatic Go typically doesn't use the `container` package.

-----


I wrote most of those already, if anyone needs them, help yourself. Haven't had the need for a bit set, but I guess I can add it to the TODO list :)

https://github.com/cosn/collections/

That being said, I completely agree that the author chose the wrong language for the problem at hand.

-----


Author of the blog post here. Some of the comments here suggest that I was probably new to Go. Not quite. I was reasonably active in the Go community (and on golang-nuts) in the first two years of Go's public life. Also, when discussions of generics were taking place informally in the mailing list, I was one of the first to have actually written at least a half-serious `proposal' for generics (you can read it at http://oneofmanyworlds.blogspot.com/2011/11/draft-2-of-propo...).

As for achieving `generic' code through static generation using an external tool, I had had considerable success with it in some earlier projects. Except that the number of types is much higher in this project, and things could not be as simply - or clearly - generated statically.

I cannot publish the code because of the client's IP involved -- not because I fear criticism; see, I was ready to face _this_ criticism :-). Those of you who read my original post in golang-nuts may have already read that, of course!

-----


This is too late to help you, but still...

BitSets: look at math/big - not that intuitive, but what you need is probably there.

Sets: I wrote https://gist.github.com/arnehormann/6234573 while thinking about an api. It's not a regular repository because I never needed a set type myself, but it should work.

Like another commenter said, the cpu usage statistics in the Java program are most likely due to Java threads you didn't start yourself, e.g. the garbage collector. If your code involved creation and disposal of a lot of Objects, Go is at a serious disadvantage compared to the JVM. But that can be mitigated with a little effort and will probably disappear in due time.

-----


I actually wrote a bitset implementation using math/big: https://github.com/kisielk/bigset

-----


I thought it was a really good article. I found you included some useful details both on relevant low-level technical aspects, as well as the more human-level process of development and client interaction.

After reading it, I thought it was really insightful and useful, and concluded you're clearly a good SW engineer - was surprised by the excess criticism here. Anyway, thank you for writing and publishing this.

-----


I found it a little surprising that Java's generics are a good fit for your task. Don't you have tons of boxed ints eating lots of memory? That's what I'm struggling with a lot when I do graph processing in Java. At that point I tend to resort to C++. Or do you use fastutil?

-----


The 375 percent cpu is probably 1 thread of work and 2.75 threads garbage collection.

-----


Honestly it looks like you don't know Go or Java very well, at least how the garbage collector works in each.

-----


What do you think about Julia? I think it would be an almost perfect choice for this project. (And I actually believe that Julia is better in almost every way than Go if you ignore libs and maturity.)

-----


The tone of this article really rubbed me the wrong way. Railing against the language design choices made by Go isn't evidence that those choices are wrong – it's evidence that you're trying to use the wrong tool for the job. I was reading this wondering why the author thought Go would be an appropriate choice in the first place. Julia does seem like a natural choice for this – there are efficient Sets as well as BitArrays and you can use the natural notation for them.

-----


I mostly agree but one argument for Go would be performance (at least in theory) and the lightweight and "fun" feel of the language.

BTW - how would you compare Julia to languages like Python, Ruby or Go? If you ignore the libs and maturity, is there anything about Julia that makes it relatively less suitable for, let's say, writing a web app, a web server or a desktop application?

-----


Your multiple core usage may be from the JVM busily using those extra cores to JIT compile (and garbage collect). Once compiled, they'll be swapped in-flight into your running code.

-----


>As for achieving `generic' code through static generation using an external tool, I had had considerable success with it in some earlier projects

Exactly. I am reminded of Rogue Wave's[1] generics before STL became part of C++. I remember achieving that effect using a paradigm of macros and code generation provided by Rogue Wave libraries. It was during mid 1990s.

[1] roguewave.com

Edit: Added reference to Rogue Wave

-----


Same here, Borland C++ offered similar tooling.

-----


Who would have thought that a brand new language wouldn't have the features, library support and optimization that the more popular languages have? Should be obvious, but then you read through HN posts with people dismissing languages like C++ and Java as 'too old' or something and that you need to use some brand new untested language to be worth talking about.

Never select a language based off hearing about it on HN or blogs. Either stick with what you know or use a tool that has very specific optimizations for the problem you're going to tackle (and no, concurrency is not a good option to jump off the JVM as it has incredible concurrency support already: see https://github.com/LMAX-Exchange/disruptor for the fastest concurrent bus I've seen in any language). Of course, there is nothing wrong with testing out golang or haskell - just don't force your paying client to test it out with you or you might be one less client shortly.

-----


There is nothing wrong with testing golang, certainly. But Haskell is 24 years old. Hardly the new kid on the block.

-----


Haskell (and Lisp) will always be 'new'. Especially going by HN posts which seem to think that Haskell is some brand new language created last week to solve the problem of 'side effects' and in a few months time everyone will be using it.

-----


I have spent part of the holidays reading about Interlisp and Mesa/Cedar systems at Xerox PARC.

Quite powerful GUI desktop systems in the early 80s, using language capabilities that are yet to be fully usable in the mainstream.

Lisp on one system, and a GC enabled systems programming language on the other one.

Every time I discovered such systems being ignored most developers, I remember of Bret Victor's talks.

-----


Don't forget Erlang. For some reason a big part of HN thinks it's an unproven technology.

-----


I don't know of anyone who thinks Erlang is unproven. Lots of us think it's weird and not worth using.

-----


Yet, your mobile phone calls might be going through Erlang powered switches.

-----


And my multi kilobuck bank transactions may be powered by COBOL, but you won't see very many developers lining up for that.

-----


Built by a company with the time, money, and motivation to train new hires on an esoteric language that happens to be specifically designed for their unique application.

(Incidentally, my mobile phone calls are quite rare. Voice communication sucks. If your intent was to show that Erlang is important to me, you chose a poor example.)

-----


GHC, the most popular Haskell compiler, is also very mature and very good at doing high-level optimizations.

-----


> just don't force your paying client to test it out with you or you might be one less client shortly.

Author of the blog post here. I agree, in retrospect!

-----


> see https://github.com/LMAX-Exchange/disruptor for the fastest concurrent bus I've seen in any language

The genious behind LMAX is the way they bend Java's object layout features; they achieve nice performance in spite of using Java, not because of it. Some decade old message passing libraries (OpenMP et al.) will probably outperform LMAX without even trying.

-----


Actually, i doubt it. The machine code that ends up running at the heart of a disruptor is pretty minimal, and it executes precisely zero lock or atomic operations when handing an object from one side to the other. I am not aware of any other message-passing system that lightweight. I would be genuinely interested to hear about one.

-----


>Who would have thought that a brand new language wouldn't have the features, library support and optimization that the more popular languages have?

Because there are "brand new languages" out there that are more mature than Go, and better than it for his needs. Scala and Clojure come to mind, but even something like Nimrod would be perfectly capable.

You mention it as if being "new" is some kind of excuse.

-----


When I first learned of Go I thought it had a very narrow use case. The language is basically simplified Java (or a reinterpretation of Java), and works on the same level of abstraction. It's not low-level like C/C++ or Rust, and not high-level "productive" like Clojure. It seemed like Java sans JVM, and as Java developers know, the JVM is the best thing about Java (some would say its only grace). It lacks the JVMs runtime profiling and monitoring tools, as well as the JVMs most powerful features of dynamic class loading and runtime bytecode instrumentation. Its only advantages, as I saw them, were a much reduced startup time and a lower barrier to entry for beginners; its only use case, I thought, was for writing fast command-line apps. Most people who seemed excited by Go were Python and Ruby developers who liked the speed boost and the easy set up.

Now I think Go actually has some very good use cases. While I would never dream of developing a large, complex or critical app on any platform other than the JVM, the fact that Go produces self-contained executables makes it very convenient sometimes. Fast command-line programs are actually not too narrow a use case, and Go is not useful just for those. I can see myself using it for other small web or network services as well. I still think Go is a JVM-less Java, or a Java Lite, but apparently Java Lite is a very useful thing to have.

-----


It's not very like Java at all. The only OO-like feature it has is interfaces, which are more like Haskell's type classes combined with existential types than anything else. (The resemblance here is actually very close, implementation-wise: roughly, vtables at the per-instance level rather than per-class level).

The other semi-interesting things it has are (a) channels + parallel functions and (b) the return of error codes for error handling.

Java things it doesn't have start with reflection, bytecode (CPU independence), dynamic runtime code generation, inheritance hierarchies, generics, "everything is an object", array covariance, exceptions as an idiomatic error propagation scheme, scoping based on nested namespaces, no code outside of classes, nested types with scoping to match, inner classes with implicit outer class self pointer, only value parameter semantics, and only reference user-defined types.

In fact most of what makes Java distinct from the subset it shares with C is missing, except for a garbage collector.

-----


It's not very like Java at all. The only OO-like feature it has is interfaces, which are more like Haskell's type classes combined with existential types than anything else.

That's a bit disingenuous, since Haskell typeclasses go hand in hand with parametric polymorphism, which Go doesn't offer.

Typeclasses plus existential types allow you to implement subtype polymorphism. But it is generally frowned upon in the Haskell community and certainly not widely used.

Disregarding implementation, if you drag in typeclasses + existential types, Java's interfaces are also comparable (yeah, they don't offer compile-time duck typing, but neither does Haskell).

-----


Java classes have to be declared to implement an interface. Haskell types don't need to be declared to "implement" a typeclass, since the typeclass instance is declared separately. You don't need to modify the original definition in order to package up a value + functions into an existential; to me, that's the essential advantage of duck typing for larger projects, where you don't have the ability to freely modify any and all source included.

-----


Java classes have to be declared to implement an interface. Haskell types don't need to be declared to "implement" a typeclass, since the typeclass instance is declared separately.

Let's be more specific: instances should be declared with the class or with the data type. Orphaned instances (that go with neither) are discouraged and with good reason - instances cannot be imported explicitly [1]. It is all to easy to have two conflicting instances if people start defining instances apart from the type class or data type. Don't do that! Luckily, -Wall will complain loudly about orphaned instances.

where you don't have the ability to freely modify any and all source included

Given the above, this is not really true in Haskell. Since orphaned instances are bad, people often wrap a data type using newtype and define the instances with that type. Of course, this is not so much different from creating a wrapper class in Java with another superclass or interface. Except that defining new types in Haskell comes with far less ceremony ;).

[1] http://www.haskell.org/haskellwiki/Orphan_instance

-----


Duck typing is an exercise in ceremony reduction, ideally to the point of no ceremony at all. We can always add another layer of indirection to act as a proxy whatever language we choose. Java and similar OO languages make it harder, duck typing is the easiest it gets. Everything else is on a continuum.

FWIW, I was more interested in the implementation details of existential types, and how similar it is to Go (except that Go does it dynamically using reflection, last time I checked). You know more about Haskell and its idioms than I do, I just know about the features and make inferences from how they may be combined :)

-----


I don't mean it's like Java in terms of particular language features, but in terms of "feel" and philosophy. It uses abstractions on the same level as Java (higher than C, lower than Clojure), designed as a blue-collar language, emphasizes readability (at the expense of verbosity), and generally avoids low-level bit-diddling as well as high-level meta-programming tricks.

-----


Ahh yes, you must be an inferior programmer if you work in language X.

Pretty much any common language other than C/C++ could be (and probably has been) called a blue-collar language - C#, Java, Javascript, Python....

-----


What? Being a blue-collar language is a virtue! C#, Java, Python, Javascript etc. are all pretty much blue-collar languages; Haskell, Scala, C++ (depends), Rust (probably; I don't know much about it) and Clojure (sadly), aren't.

But you're right: "white-collar" languages have the habit of never being too popular.

-----


There were days when Python was white collar.

There are places where C++ is blue-collar. (Games, for one.)

Rust is meant to be white collar, seems to me.

-----


If "blue collar" means "used in industry for real work", and "white collar" means "a research/niche language", Rust is designed to be blue collar. It's not designed to be a testbed for research beyond what was needed to get safety out of zero-cost abstractions.

-----


Let me revise my previous comment. While many might categorize Python, Javascript and Ruby as blue-collar languages, they do encourage all sorts of metaprogramming tricks, while Java, C# and Go absolutely don't. I think this is a big philosophical distinction, because the second group favors readability and the ability to share code in a large team over language power, and this is what makes Go much closer to Java/C# in its philosophy than to Python et al.

-----


the second group favors readability and the ability to share code in a large team over language power

Not to pick on you, but people say this all the time, as in it's probably the thing people say most often on this subject, and I wonder: do we have any evidence for it? That is, do we have any evidence that the mid-tier languages which eschew more powerful abstractions (Java and its peers) lead to either more readable or more shareable code? Or is it one of those things that everybody "knows" but ain't so?

-----


Well, I can't claim that that's the case, only that those languages' designers think it is. There are some things we do know, if only anecdotally (maybe there's been some research on the subject – I don't know). We do know that C++ was a real boon when it first garnered wide appeal, but that very quickly large teams began to curtail the use of some of its more advanced features because of that reason. We also know that people have been writing much larger projects in Java (and possibly C#) than in any other language in history, certainly relative to the effort invested (there might have been larger C++ projects). Some of it just seems intuitive (though may not be the actual case). The problem is that it's hard to gather data because the languages adopting this view are the ones that are most popular, which helps them get selected for large projects to begin with. But we might have more data soon. I think JavaScript is the first "magic encouraged" language that will be used in multi MLOC projects. Ruby is more "magical" but doesn't seem to be favored by large teams working on large projects. So we might know more soon.

Personally, though, I think that's the wrong issue. Whatever extra productivity is gained by language magic, we're not talking orders of magnitude here. Usually it's mostly about developer enjoyment, lack of annoying boilerplate etc.. These are annoying issues, but not critical ones. I think the most crucial issue is state management, which can have an order-of-magnitude difference for some projects, as well as a significant effect on performance and scaling.

-----


Most everything you're talking about is explicable by popularity effects. That's why more objective study would be interesting. Alas, I doubt it will happen: serious research on software engineering, as opposed to the thin broth we have now, would require at least an order of magnitude more funding, and no one's likely to provide that.

I'm not sure I like your distinction between developer enjoyment, lack of boilerplate, and state management. To me those things all have to do with good design.

-----


Blue collar worker just usually means "one who is uneducated and unskilled". Putting that onto languages is sort of demeaning... it sounds like that's not really what you meant, though, and that's cool, just my misunderstanding of your meaning.

-----


That's just how James Gosling described Java when he explained the philosophy behind it in 1997[1]. He wrote, "Java is a blue collar language. It’s not PhD thesis material but a language for a job. Java feels very familiar to many different programmers because I had a very strong tendency to prefer things that had been used a lot over things that just sounded like a good idea." He most certainly didn't intend the term to be demeaning, but more to contrast it with research languages that include features that are untried and unproven. The term has since been used as shorthand for Java's (and languages like it) goals and philosophy.

[1]: http://dfjug.org/thefeelofjava.pdf

-----


Uneducated I'll give you, though probably it should be qualified by something like formally educated, but blue collar certainly does not mean unskilled.

The paradigmatic blue collar job to my mind is not taking orders at McDonalds, it's welding.

-----


I knew I should have qualified that more. You're right, McDonald's is not blue collar, but working in a manufacturing plant riveting part A to part B is. It also encompasses stuff like mechanics and welders that do require skill and even some education and certification.

But regardless, most of the time it's still used to mean something lesser.

-----


Not sure if I'm reading your response incorrectly... but go has reflection. I'm not sure what you mean by scoping based on nested namespaces.... Go has similar scoping to pretty much every other modern language. Are you saying java has no code outside of classes? Because Go has that (and doesn't have classes).

Also... Go has OO features. You can make an object-like thing by tying data (a struct) with behavior (methods tied to the struct). It doesn't have inheritance which is not the same as not having OO features.

-----


I think you think I'm criticising Go. I'm not. Beyond that, I think you misunderstood my response.

-----


Yeah, I figured I was misunderstanding you. It seems like you were giving a list, half of which was stuff Go didn't have and half of which java didn't have.... anyway, no big deal, just trying to clarify.

-----


I use Lua for fast command-line programs. If that were to not be fast enough (and I'm not sure Go is faster than Lua but let's assume it was), I'd go with Rust which manages to be both lower-level and higher-level than Go at the same time.

-----


There's no doubt Rust is more "important" than Go in the sense that it may have a much greater impact on the software community, but the two languages don't seem to be comparable at all, and they certainly don't compete. Rust is more complicated than Go (it should be, as its more ambitious), and aimed to replace C/C++. Go, as I said, is Java Lite (and like Java, a blue-collar language). Go is great when you want to write a smallish, self-contained Java program and want to spare yourself writing a startup script and requiring (or packaging) the JVM. (I don't know anything about Lua)

-----


Wow, go is totally not Java-lite. Trying to program in it like it is will just cause headaches. The only conceivable way that I can think of that it could be called that is because it is compiled and has a garbage collector. Otherwise... they are very different languages.

Go is what you'd get if python and C had a bastard love child that turned out different from either, but still retained some of the beauty of each of its parents.

-----


And Nimrod would be their legitimate favorite son.

-----


> Go, as I said, is Java Lite

Or Python+.

Interesting all the comparisons to Java, with me coming from an environment where Java is never used, never considered, largely never thought about. If Java is mentioned at all, it's usually something like "my kid took a programming class in college, and they used Java, why would they use something like that?". I suppose Cobol was like that: widely used, very widely used, but not used at all in many circles.

-----


Probably more accurately Python--; it cuts out a lot of features from Python, a great deal of which you weren't using, some others of which there are other ways to do, and ends up with a simpler and also much faster language, in which you will sometimes miss a Python feature, but in my experience not as often as you might think. But definitely non-zero.

(By "not using", I mean for instance that in Python, like Javascript, at any moment, you may set a new method on a particular instance, and the Python runtime must deal with that, such as by spending a lot of time looking up references that never actually change in a real program. This is a really expensive feature that you are paying for all the time, yet rarely using. A great deal of the JIT speedup you can get in such languages is working out how to skip those lookups optimistically until someone actually changes them.)

-----


I miss Python's named parameters with default values. They are surprisingly hard to replicate in Go. Also list comprehensions.

-----


Named parameters can be sort of gotten by passing a struct as the parameter, then you can do

type fooParams struct { Name string Age int Address string }

foo( fooParams{ Name = "Bob", Age = 24 } )

Defaults are a lot harder to do in a way that doesn't just suck. You can make a DefaultFooParam that has all the defaults... but it's not pretty.

List comprehensions never seemed like a big deal to me. It's 3-4 lines for a loop, which is probably easier to read than the list comprehension anyway.

-----


> List comprehensions never seemed like a big deal to me. It's 3-4 lines for a loop, which is probably easier to read than the list comprehension anyway.

that's totally a nope.

    def qsort(L):
        if len(L) <= 1: return L
        return qsort([lt for lt in L[1:] if lt < L[0]]) + [L[0]] + qsort([ge for ge in L[1:] if ge >= L[0]])

-----


I just saw this several days late, but have to comment.... is that really the example you're giving of a list comprehension that's easy to read? Because... yeah no. If I saw this in a code review, the first thing I'd say is "this code is illegible, please reformat to make it easier to read"

This is classic "I'm trying too hard to make my code look clever rather than make it readable and easy to understand".

-----


Unlike Cobol there are few circles where Java, or at least the JVM, isn't used. The ones that come to mind are .Net shops, hardware/embedded shops, very specialized applications (scientific, etc.), console game developers, or – and this is probably the largest one – small(ish) web startups: your Ruby/Python/Javascript crowd before they need to scale. Many of those in the last group would still have some Java/JVM.

-----


> [...] there are few circles where Java, or at least the JVM, isn't used

I was making the very opposite point. I think Java programmers tend to underestimate the circles where it is not used. In particular, it seems that those who would not describe themselves as professional programmers but who nevertheless need to program tend to not use Java. And it's not all Python/Perl/Basic/Tcl/Bash; C++ (and C) are also widely used.

-----


The people being excited by a language have nothing to do with what the language is like.

I see Go as a C-like language with some of the annoyances cut out and a garbage collector added. You don't have pointer arithmetic, but you still have pointers.

When you look at it that way, the lack of generics is not so annoying.

The best part of Go is the fact that it forces error checking.

-----


> The best part of Go is the fact that it forces error checking.

Except that it doesn't. Otherwise you would be forced to check the return type of fmt.Printf() and gang.

-----


>> > The best part of Go is the fact that it forces error checking.

> Except that it doesn't.

Depending on the value of "forces" used. Maybe "forces" in the sense of "only viable option for someone not programming foolishly."

-----


Ok. So idiomatic go returns multiple values with an intention to return an error type. I guess fmt.Printf() is an exception.

For the most part, it does as well as C does.

-----


> For the most part, it does as well as C does.

Which isn't saying much really :) There is absolutely no way to force you to handle errors in Go.

-----


> Its only advantages, as I saw them, were a much reduced startup time

Even that can be solved when using one of the many native compilers available for Java.

As the OpenJDK does not have one, people tend to forget other vendors have them.

-----


Can you recommend some good native compilers? Excelsior[1] is the only one that I've read good things about, but I haven't tried it.

[1] http://www.excelsior-usa.com/

-----


I know a few from conferences, but never used them on projects myself.

Besides Excelsior, there are Aonix PERC, IBM J9, Codename One, JamaicaVM, RoboVM.

There are probably a few others.

Mark Reinhold mentioned on his "post Java 8" talk at Java One, that having an AOT compiler as part of the standard JDK is part of the wishlist.

-----


Avian (http://oss.readytalk.com/avian/) also has an AOT compilation option.

-----


How does having a "native" compiler reduce the startup overhead of the JVM? That doesn't make any sense.

It may reduce compile times, but ultimately the reason startup sucks is because the JVM is huge and has to load everything and the kitchen sink in order to function for even the smallest programs.

-----


Because when you compile to native code ahead of time:

1 - There is no JVM

2 - All the code that is not used is not part of the binary, if you do a static build

2.1 - There are native compilers for Java where you can give exclusion lists to allow certain code to be kept even in static builds to allow reflection use

-----


OK, we are not talking about the same thing. I was thinking along the lines of a compiler written in a native (non-jvm) language ala jikes but you are referring to a compiler that compiles to a native executable ala gcj.

I've experimented with gcj in the past. It still suffered from excessive overhead, still had it's own runtime requirements (although obviously not the same as the JVM) and had a lot of serious compatibility issues. Not something I would have based a serious production deployment off of personally. Maybe the state of the art has changed since then.

-----


gcj was a toy compiler, a 2nd class citizen on the supported gcc languages, left to rotten.

It was never at the same level as commercial Java native compilers.

-----


I also once had this idea. Because Go is mostly the only matured language which can describe processes and pipes in a program with solid flow control. But still, it doesn't feel nice to interact with shell…

-----


the CPU utilisation ... was around 370-380%! I was now totally stumped

I guess that his code allocates a huge number of objects as all input and output classes are final. The JVM's garbage collector is able to run concurrently, so I guess it's the GC that takes so much CPU. AFAIK Go uses mark-and-sweep collection which is very slow.

That would explain the unexpected difference in running time as the JVM's garbage collector is very mature and fast.

-----


When Go is slow, it's almost always due to excess garbage creation. This can usually be fixed by optimizing your memory usage... but I'm guessing an experienced java professional may not think of that precisely because java's garbage collection is so damn good most of the time.

-----


I know theres a []byte mempool project on github.[1]

Still pretty early though, I don't think it can do dynamic sizes?

[1] https://github.com/thejerf/gomempool

-----


Pooling dynamic sizes is a bit tricky; if a user requests 1000 bytes and you hand them 1000 bytes, you're in some trouble if the next guy asks for 1002. I round all allocations to powers-of-two in there.

It does dynamic size but at the moment I don't have separate per-bucket pooling settings; it's the obvious next feature. The stats collection is intended to show me whether that's a useful feature. In testing so far it hasn't been in my specific use case, but I'm still only hitting my application with load testing, not real load.

The use case for gomempool is relatively transient buffers, where that is a win vs. generating a lot of []bytes. Rounding to power-of-2 is a traditional, theoretically solid answer. There's also as somewhat more unusual one using Fibonacci numbers, which Erlang uses to size its memory hunks. Fortunately the interface is agnostic, if that's advantageous someday user code doesn't need to notice the difference.

I couldn't resist the first time in my career in which I could justify some bit bashing: https://github.com/thejerf/gomempool/blob/master/pool.go#L39... :)

-----


Most of the time it's really just a matter of reusing data structures rather than creating new ones and throwing them away immediately, over and over again.

-----


Yep, I think that's basically the idea there.

"You already have this []byte, don't throw it away, give it back to the pool so you can reuse it."

-----


Yep all that extra CPU utilization on the the other cores is just garbage cleanup.

Go has a stop the world collector, hence the poor performance and single core usage.

Both versions would benefits greatly from reusing instances instead of generating huge amounts of garbage, however the Go version would benefit the most. With the Java version he is simply throwing hardware at the garbage.

Know thy garbage collector!

-----


Seems that 2014 won't be a good year for Go on HN. Same old story as with Node and Mongo. First they ignore you, then they praise you, then they hate you.

-----


Those three steps are basically:

- New technology is introduced. Nobody's really heard of it or used it, so beyond a few "Look at this new thing!" articles, nobody talks about it.

- The technology gets some penetration. New users pick it up, probably because it solves some issue or irritation they have. They write about how the technology helps to deal with it, or why it's interesting; if it didn't/wasn't, they'd probably not bother using it, and would be pretty quiet about the whole thing.

- If the technology made it this far, there is an explosion in popularity as more people pick up the tools and use the technology. Typically this results in quite a few people using it in the wrong way, or because it's the current 'hot stuff' (rather than because it will solve a particular problem), or maybe picking it up a little bit too early. Lots of these people will write about how the technology sucks, or how it doesn't solve particular problems. That's fine; it's the public knowledge-gathering phase, and although there will inevitably be a lot of negativity, other people will discover the benefits, and the technology will frequently evolve to address popular concerns.

- The fourth step, that you didn't mention, is that the technology and discussion around it becomes more "mature" - it's widely-used, everyone's more-or-less aware of the pros and cons. There will be the occasional post called "X Sucks, I'm Moving to Y!" or "Why I'm still using X and not Y".

tl;dr: that's the way it goes - it takes a while for new technology to work out the kinks and for the community to understand where and how it should be used. And while that happens, they'll talk about it.

-----


http://upload.wikimedia.org/wikipedia/commons/9/94/Gartner_H...

-----


Once you've embedded the Hype Cycle in your consciousness, it's amazing how often new technologies follow it. Also interesting just how worked up people get at each peak and trough... :)

-----


There's always been blogs complaining about Go and the generics issue raised in this blog is something that crops up in every discussion about Go.

The problem with heavily hyped languages is that some people jump on the bandwagon without really thinking about the problem they're having. And this is exactly what the author of this article seems to be doing. If you're having to convince your clients to maintain a project in a language neither of you have developed in and you guys already have experience in other languages, then the question should be "what will I gain from switching to Go". The author's justification seemed to be "It's hyped online" rather than any technical justification; and that strikes me as a poor decision from the start.

-----


What?! I you might want to reread the article and then read the author's comments here and his other Go articles.

The author clearly knew about Go's lack of generics and was quite familiar with the language. After stepping away from the language for a while he decided to give it another try in a project where he thought the lack of generics could easily be worked around via Go idioms. He found out that the lack of generics _did_ hurt more than expected and wrote about that part in a way that projected his frustration.

-----


Go never intrigued me anyway for that matter. It's supposed simple syntax was not enough of a motivator for me to chose it over a higher level language (Clojure, Scala, Etc) that requires a bit more elbow grease to become proficient it.

-----


The way I see it, there's very little compelling about Go to outweigh its shortfalls and I don't see it getting mainstream any time soon, if ever. If languages were stocks, I would have shorted it long before the HN hype started. Then again, I feel pretty much the same about the whole crop of hip languages du jour (scala, clojure, erlang, haskell, ...)

-----


For those of us coming from Python, Perl, etc., Golang brings performance and concurrency in a format that is easy to pick up and integrate.

I have not touched C in almost 20 years, but I was able to write a concurrent program in Go that outperformed a similar multiprocessed Python script by about 5X in roughly one day. Go does not have the same library depth as Python, but the stdlib is pretty good.

The thing about Go that is similar to Python is _my_ performance is good, and I don't have to expend much effort in boilerplate code, or learn a coding approach that is unfamiliar, yet I still get relatively high performance.

Go won't replace Python for me, until things like matplotlib and Pandas become available, but it make an excellent addition to the toolkit.

-----


This is the kind of article we need more of on Hacker News.

The author chose a newer language to build a real project in and then gave us an evaluation of how that language worked as a tool.

This is far superior to the typical benchmark-game blogs that try to compare a few languages using only a small test program.

-----


being able to do minus, union, intersection, etc. I had to code those in-line every time.

I'm not sure I understand the post author's complaint here. What's wrong with writing your own SetDiff, SetUnion, and SetIntersection functions and doing stuff like the following?

    baz = SetUnion(foo, bar)
(I have done very little programming in Go.)

-----


The problem is that you would need to rewrite that code for each type of foo and bar.... so if you have a set of ints and a set of strings and a set of SomeStruct... they'd all need their own implementation.

This is where code generation can work really well, especially for boring crap like set functionality... but he's right that rewriting it each time you figure out you have a new set type is a pain in the butt.

-----


If the base type of the set is a bit set, the function need only worry about the position of each bit, and not the intended type. Of course, if the set has content in hash buckets (or a similar scheme), you would need to pass in some kind of comparator function/callback.

I say this as a former C programmer used to doing such things to make library routines like "bsearch()" work.

Too many things in Java rely on subclassing, rather than functional composition.

-----


What is the (declared) type of `SetUnion`? Don't forget, Go has no generics/parametric polymorphism.

-----


So, are you saying that it's impossible to declare a function without generics? How did the world run before generics were invented?

-----


> How did the world run before generics were invented?

We used code-generators or pre-compiler macros or dynamically typed languages or we hand-wrote heaps upon heaps of boilerplate.

It sucked.

And regardless, Go only offers the last option.

-----


The author said that he needed a generic set for different concrete types, so he'd have to write a bunch of these functions for all the combinations he needed. And he did. And it was a mess. And it was also slow.

Edit: not that we can conclude anything from the lack of performance, though, we don't know how it was written.

-----


I believe it was a mess. But i don't believe it couldn't be done correctly in Go or whatever language you take.

-----


My guess would be too much "noun oriented thinking".

Some of us came of age before the tyranny of King Java, learning such obsolescent tools as Pascal, Lisp and C back in school. (I'm gonna ignore BASIC and FORTRAN, other than as examples of what not to do) We learned how to pass around individual functions/procedures to support library code.

http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom...

-----


No, the problem is that SetUnion needs to be implemented six times for six different data types.

-----


Well, as we all know, Go does give you a way, sort of. You'd have to write basically a dynamic version using interface {}, and then write wrappers casting the values in and out, and possibly handing out the equality predicate.

That sucked in Java at the time, though, when you had to screw around casting Objects in your code, I don't see why people would prefer that.

-----


Surprisingly, Erik Meijer (Haskell, C#) can somewhat see the appeal of no generics and a bit of casting:

22m-31m http://www.youtube.com/watch?v=on5DeUyWDqI#t=22m

(I give myself and Google a pat on the back for being able to remember and quickly find this!)

-----


Thanks.

-----


For the app being described, would there really be six different type signatures required?

Generics would absolutely be nice for Go, primarily because they would allow the core libraries to provide all of these rich collections. However if we're discussing the notion that someone can write these themselves, it just seems contrived that people think generics are critical for any specific app -- in the example he described, it sounds like he would need one single concrete implementation.

-----


No, only that in Go it's impossible to abstract the code that implements the "set union" functionality into a function.

-----


I'm going to disagree:

    new_set = old_set.union( another_set, element_comparator_func);
If you allow some helper functions or an interface to do things such as compare/hash members, it's totally doable. Extra points for passing the helper(s) into the constructor.

Yes, you can still mismatch set types, but the casting/type-assertion in the helpers will fail with an explicit reason.

-----


Almost forgot: in Go, classes aren't "closed". While you cannot "monkey patch" and change existing methods, you can define new functions, such as my_set_comparator, that accept each given type as "this". You would then make a new interface, such as my_set_element, which defines method my_set_comparator, and any data types for which you had defined my_set_comparator would automagically meet the new interface.

-----


What's wrong with having them in the standard library?

-----


Disclaimer: I use Java professionally on a daily basis and am learning Go in my free time.

I totally agree with all the points which most of you make. Firstly, you should almost never choose a language / technology which you want to learn when you are being given paid contract task to accomplish. It might be different at your full-time position, when picking new tool (after agreeing with the rest of the team or people making decisions) might really be a viable choice, giving you an edge in the end.

Beside that - if you're being paid by the hour, if you had been able to find a client who is willing to pay you for you to learn new stuff - stick to them as them as long as possible. Most of the clients with whom I had been dealing with would just fire me or terminate the contract.

As for the performance - and I'm not defending Go here - with discrepancies that big, I'd just assume that I don't know language and all of it's quirks and it's just me not using it properly. I know that you might had spent time profiling and optimising stuff, but sometimes the overall design of your program might be violating some of the rules of given language, punishing you with performance issues in the end.

(check http://www.techempower.com/benchmarks/ and the difference from first iteration to the last one, when people knowing each framework tested started pushing their favourite toys to give them an edge with misc optimisations)

From the two language which you had tested, Java was a way better choice here - no amount of hype around a language should win over mature libraries which were just suited for your job.

PS: and yes, I'd love to see generics in Go and can't understand any of the reasons for no.

-----


tldr: I will be using a lot of generics and do tons of set operations. I will chose Go, a language that doesn't have generics and sets.

(I won't post the Go code for criticism, and I couldn't stand golang-nuts)

-----


So... if you need any data structure other than an array, a hash table or a channel, you should skip Go and find some other language? That's kind of limited.

-----


No, the problem is that he needed Sets of many different kinds. It's perfectly straightforward to implement data structures in Golang; it's just hard to make them work for a variety of types simultaneously.

-----


> it's just hard to make them work for a variety of types simultaneously.

That's sort of what you expect from any given implementation of a data structure and its related algorithms, though I imagine that some specialized implementations benefit from having them tailored to their concrete types. Examples, anyone, please?

-----


and; go isn't the best language to write everything in.

I think that's a fair conclusion for him to have drawn. He certainly wasn't hating on go.

(golang-nuts is openly hostile to any kind of criticism, so much so that there's been talk of a community code of conduct; which the community didn't want. I don't blame him.)

-----


What struck me is how naive the author is when he notices multi-core usage in a single threaded java program and proclaims: I still do not know what is going on inside the JRE as the program runs, but I am truly amazed by its capabilities!

Yeah it's magic, it multithreaded my code, or um I don't know the garbage collector maybe?

-----


Anecdotally, I think that I'm noticing a trend wherein people coming from a strong Java or C++ background (or other strongly OO languages) object to Go vociferously (typically citing generics and a couple other pet peeves) and people coming from dynamic languages (or other languages lacking generics) seem to have no problem with it. I think it may be a matter of which paradigm you're approaching Go from.

-----


Possibly.I regulary use both static and dynamic languages and lack of generics was one of my biggest complaints. If it's a static language, I want generics. If the language is dynamic I don't really care (although some dyn. languages have generics).

-----


I thought it was a pain in the ass until I realized golang really does have a sort of dynamic parameter:

    func test(myVar interface{})
will accept any type at all. You can then use Go's type switch or a call to reflect.TypeOf() to invoke different behavior based on the parameter's type. To my way of thinking, it's pretty simple.

-----


Rather than storing data structures directly in the hashmap, I would store them in an array and map the keys to array indexes.

Then the types of the hashmaps would all be the same (all map key->integer), and I could develop reusable procs for each set operation.

-----


> Rather than storing data structures directly in the hashmap, I would store them in an array and map the keys to array indexes.

Author of the blog post here. That is one of the reasons I shifted to using bit sets: specific element types can be elided.

-----


Wouldn't that mean an extra level of indirection while dereferencing?

-----


Yes, but so does run-time generics somewhere along the line.

-----


Really? AFAIK, compiler creates those functions/classes from corresponding generics (it is called templates in C++, and it really acts like template in C++). Hence, they are compile time.

I believe, it is the same in Java, too: http://docs.oracle.com/javase/tutorial/java/generics/erasure...

-----


Well, yes, compile-time generics are compile-time. That's why I said "runtime".

-----


Yes, but you are recommending he do that in Go, so by having an extra array lookup you'd be further slowing down the Go program, which he says is 5x slower than the Java program already.

-----


I still smile when people get surprised by the performance of java. A bunch of people remember the loud people yelling "Oh Java is really slow and sluggish" while whispering "as long as you compare it to C++ with arbitrary optimization time, in a good use case". Truth is, java can be darned fast if you want it to be.

-----


Truth is, java can be darned fast if you want it to be

Yes, I'm not a Java programmer, but I'm convinced it can be very fast.

But throw a rock and you're bound to hit an insanely slow Java GUI application or a web service that needs 10 times as many servers as any sane implementation would use

(and cost X million of my tax-paying money.. fucking consultants :)

-----


Java-based GUI applications often being ugly and sluggish perhaps unfairly tainted the reputation of the language and VM.

-----


Mostly because they were developed by programmers that failed to understand how to proper use Swing.

It is incredible how, regardless of programming language and UI toolkit, people still take the easy root and do heavy work on the UI thread. And don't make proper use of widgets customization capabilities.

-----


C# with the WinForms API is the only desktop GUI programming I've done and I found both the process and results very pleasant. IIRC I was fairly well behaved and used the "BackgroundWorker" in a few places :-)

-----


Note that the different readers in this discussion point out that the whole "magic" of article writer's Java implementation being so much faster is most probably the only thing that can run in parallel when you write the single-threaded program: the JVM's garbage collector.

Which in turns means that the most of the "computation" performed is actually the creation and collection of the always new objects, which people who ignore the lower-level aspects of their programs consider being "zero-cost." Which is not.

-----


There wasn't a good description of what overall task his program was trying to do, or any source code showing how he approached maps, etc. Other than that, it sounds like proof. Of everything.

-----


This rubs me the wrong way too.

Go is different and maybe there is a good representation of the problem in a pattern that is different of what he is used to. Or maybe not.

We'll never be able to find out, as the article has no details at all on the actual data models and transformations he was trying to perform. Just rant.

-----


Also, it sounded like he was comparing single-threaded Go versus multi-threaded Java?

-----


more like he was surprised that java did parallelization behind the scenes.

-----


I'll be honest, I'm surprised by that!

-----


I'm too! I don't program in Java but I've never read that the compiler or JVM can do anything like that automatically (making the user's code running in parallel even if the user didn't specify anything).

I suspect that what he observes is the garbage collector running on more cores at once (AFAIK it is designed to run so now) and that the garbage collection was the cause of the slowness in Go too. I persume he managed to have a heck a lot of allocatations and that caused the slowness of Go and the full-throttle GC run in Java. But this is just a guess. If anybody knows more exact details please write!

-----


Go can't be really mono-threaded unless you are trying to do so (or your program is really short).

A lot of the standard operations under the hood are in fact executed in goroutines in a pool of threads. IOs are, for example. So you found yourself gaining all the advantage of asynchronism without supporting the cost in the code... exactly like this example in Java.

-----


http://golang.org/doc/faq

Why doesn't my multi-goroutine program use multiple CPUs?

You must set the GOMAXPROCS shell environment variable or use the similarly-named function of the runtime package to allow the run-time support to utilize more than one OS thread.

Programs that perform parallel computation should benefit from an increase in GOMAXPROCS. However, be aware that concurrency is not parallelism.

-----


I think he forgot to set GOMAXPROCS.

-----


Author of the blog post here. Thank you all for your insightful comments and critiques. A few points.

-> Several people have suggested that JVM's mature GC may be using other cores, resulting in the > 370% CPU utilisation. I admit that I do not understand the internals of OpenJDK's GC. However, I would like to point out that 100% of the roughly 1,200,000,000 statistics results instances created during one run are not released until the program terminates. They are all stored in statistics results containers until the very end of the run. However, see below.

- From a processing perspective, other than the manipulation of containers and bit sets, almost all of the remaining processing is numeric. It is full of integers and doubles getting added, subtracted, multiplied, divided, square roots calculated, etc., as part of various statistical computations.

- Where I needed sets was in preparing the several million working sets over which processing iterations occur. Working sets are prepared based on user's query criteria, several thresholds for filtering elements under a variety of constraints, etc. From a garbage perspective, these working sets are the biggest garbage generated during a run.

- Go's numeric performance is certainly very good. I have had good experiences with it in other projects.

- It is true that I could not identify the causes to which the performance differences between the Go version and the Java one could be attributed. Was I being naive? Am I incompetent? Possible. As I concluded, this behaviour may be obvious to more informed people, but it surprised _me_, and, that is what I admitted.

-----


Did you by chance profile the Go program to see where the hot spots are?

-----


I still think that the way you are criticising the author is nonsense.

I totally agree that programmers need to use the right tool for the job but;

Most of the programmers will not know the core implementations of a programming language when they started using it.(even after a couple of years) This leaves them only one choice to decide if it can replace their primarily preferred language or not. Trying out the language.

If it gives a bad taste from the beginning, doesn't ease the implementation, or better performance, then programming language won't have much chance, will not get attention and growing community.

This is why Ruby got a popular community with the help of Rails framework. Developers found it very very easy to develop apps, it was very much readable code, and you save lots of time in order to get the app up and running. This advantages just made people ignore all the disadvantages of the language. (concurrency, being hell slow, etc.)

As much as i want to try out Golang one day,code examples on internet doesn't blow my mind like "wow, how smart that is!!"

-----


Of course Java is the best solution for any problem, who could dare to think otherwise. It is mature, stable, incorporates millions of man hours (of solid mediocrity) and there are no shortage in coders and believers.

http://chrisdone.com/posts/dijkstra-haskell-java

-----


It has a state-of-the-art Virtual Machine, rich concurrency facilities (why does everyone forget this?), reasonable type safety, great tooling, and it operates within a diverse ecosystem of languages using the same infrastructure.

But yeah, I have always liked the argument of throwing a curve ball at the kids who were already programming in imperative languages. It also levels the playing field and those who hadn't had any prior experience tend to perform better without feeling so inadequate next to their peers.

-----


Rich concurrency facilities based on pthreads and murexes provided by an OS, so no miracles here, just the same broken by design stuff.

-----


Care to expand? I still find that Java's are some of the best concurrency libraries you'll find, among imperative languages or otherwise.

-----


Java of today is not the same as Java from 2001.

-----


Dijkstra's argument was more about Haskell than Java... well, except the trash talk about Java's origins, you can't change those.

-----


"Someone in 2001 wrote..." click X

-----


> Russ Cox' original formulation of the now-famous tri-lemma is incomplete at best.

Could someone give a brief introduction to what this sentence means? I have absolutely no idea about any of it.

-----


probably this: http://research.swtch.com/generic ? go had 3 options for implementing generics:

1. leave generics out : the c way (slows programmer)

2. do it at compile time: c++ way (slows compilation)

3. box/unbox everything implicitly: java way (poor perf)

-----


Also look at a list of proposed ways to add generics (and why they didn't make it): https://github.com/remyoudompheng/go-misc/blob/master/generi...

-----


Hm. Which of these does C# use? Which does Haskell use?

-----


Regarding C# it depends on which compiler you talk about.

Microsoft's current JIT/NGEN, generate a single version for reference types and a separate version for each value type. So a mix of Java/C++ approaches.

Not sure what the new JIT/NGEN compilers, RyuJIT will use.

I also don't know what approaches are taken by Mono, Bartok and IL2CPU, but they might be similar.

-----


Yep, now I can see why this is trilema is "incomplete at best" - c# and other use what can be described as a mixture of these three approaches.

I was going to say that the c# compiler is fast enough despite this, but then I remembered that one of go's selling points is that the go compiler is blindingly fast compared to languages such as c#. Perhaps maintaining that performance with generics is a real issue.

-----


Although any language with modules is fast enough, compared with C and C++.

Many old timers like myself can remember the blazing fast compile times of Modula-2 and Turbo Pascal compilers in MS-DOS systems.

Go compilers also lack a strong optimizer, which is tends to slow down compilation.

-----


I believe C# does it at runtime for reference types, and compile time for value types, so that you don't eat the cost of boxing at runtime. It doesn't make sense to make separate compile time generic types for reference types in C# since the type is basically constrained to using system.object members anyway (unless you add type constraints to the generic type class definition).

-----


Haskell: A mix of 2 and 3.

-----


It's ironic considering that the Go developers want the best for the programmer (That's why they work so hard on the Go tool for example).

-----


Well, the default case (leave them out, make do for the time being) allows the option of adding generics later on (in a hypothetical Go 2.0 or later).

Using a half-baked model and implementation now boxes the language in later on.

-----


That's ridiculous, we get articles complaining about the lack of generics in Go daily now. That's like complaining about the lack of type safety in ruby. Go warns clearly that it doesn't comes with generics. Need generics? Use something else, we all know Go doesn't have them. Nice way to get on the HN front page though.

-----


Am I the only one who thinks writing my own Set data structure (based on a map under the hood) isn't crazy at all?

-----


If you're not the only one then you can all meet up in a month and each point out bugs in the other n-1 implementations.

-----


Does a set do so much that you'd be worried about doing it wrong? Not to say having it in a common mature library wouldn't be an advantage, but it's something I'd be pretty sure I could implement and get right the first time.

I'd be more worried about having two programmers write two implementations in the same project with subtly different interfaces, and having different parts of the code use each one. This is a cost and maintenance problem, but that's also a social and communication problem common to all projects.

-----


Yeah, I was exaggerating a bit, but yes I think there could be room for bugs depending on what more involved operations are offered beyond basic membership tests.

Anyway, have you seen the map[T]struct{} idiom for Go? Decent enough for the basic case.

-----


Nope, I posted this gist in a comment on the parent already:

https://gist.github.com/mediocregopher/8319986

-----


My rule of thumb is to use a language for something a domain that its community uses it for. Python for scientific programming, Ruby or nodejs for web servers, PHP for embedding dynamism in a static site. Then you're more likely to find libraries and support, and to find adoption for your own libraries and pull requests.

This doesn't mean you're always safe even on a language's home turf (Rails and Node each had significant problems as a server platform for their first, hyped, years), or that it's never worth stretching the domains that a language is used for (that's where Ruby's Rails and Python's Numpy came from), but you should recognize that you're out on a limb when you do so.

-----


>Ruby or nodejs for web servers You haven't tried go, have you?

-----


Note to self: don't try to foist an unfamiliar language on a client without actually knowing if it will solve the problem efficiently.

-----


> However, considering the fact that statistics instances are write-only, I hoped that Go could help me make the computations parallel easily[1].

I'm actually dizzy from shaking my head too much while reading this.

-----


$GOPATH is my biggest issue with Go. I'd much rather have some sort of config file than have Go determine anything from my project path.

-----


i had my reservations too, but then somebody told me that GOPATH is like a virtualenv for python and then everything was nice again.

-----


I'm not a Python user so I can't really compare. I still don't agree with it since it forces longer paths to get to your project, and I wouldn't really call it isolated.

-----


The author says go doesn't have generics, and he had to rewrite the same set operations for each type that he used. Would this not work?

https://gist.github.com/mediocregopher/8319986

The items in the sets don't even have to be the same type

-----


"The general attitude in Go community towards generics seems to have degenerated into one consisting of a mix of disgust and condescension, unfortunately."

I think this attempts to make the practical state of generics in Go into some sort of religious disagreement, which is unfortunate, as that isn't the case whatsoever.

Whenever the topic of generics come up, the prevailing sentiment is that they would be great, but that the Go creators have some implementation difficulties and some competing goals that make it impractical at this time. I don't believe I've ever seen anyone of consequence in the Go community treat generics as anything other than "would be really nice".

It is a gap in Go and is widely treated as one.

Go absolutely needs more robust collection types, however. Total agreement on that.

-----


It's not a religious disagreement between the Go team and those asking for it. The Go team has simply stopped talking about it. But the reactions by the community to people bringing up generics on golang-nuts has become outright hostile.

-----


That is more about group decorum than any technical debate.

Generics have been discussed to death regarding Go, and there is a long and complex history of the choices and realities in Go. So it is understandable that people can get a little irritated when someone stumbles in and declares that maybe Go should add generics, usually then decorating their claims with lots of exaggerated hysterics (most recently that Go is an "embarrassment" because it lacks generics. Quite the accolades for the people who work long and hard on it).

-----


Refusing to debate the issue is not understandable at all, especially because the Go team has not rejected generics on principle.

The most popular response to any language debate seems to be "it's not a problem in practice", implying all critics just "stumble in" and don't know what they're talking about.

-----


They are not refusing to debate.

They have debated this many times over in the past.

What they don't do is repeating that debate every week. It would take a lot of their time and is largely pointless (in the sense that person that starts the debate with 'go sucks because it has no generics' will not be convinced that it was the right (or at least practical) decision to make regardless of how cogent your arguments are).

-----


I don't want to force anyone to take part in a particular debate if they feel they have nothing to add. But not taking part in a debate and denigrating those who do want to debate an issue are two very different things. It's the latter that irks me.

-----


Well, a good example is that we literally had the golang generics conversation on HN yesterday. Forum goers are not machines; fatigue can easily set in. What can be perceived as hostility to those who desire debate can just as easily be people who are tired of the same "debate" over and over again.

That said, that's when a community should write up an faq[1] and then simply point to it in a polite way that avoids engaging in the same conversation again while still being welcoming to people thinking of joining that community. If people aren't doing that, it's somewhat understandable, but long term the acrimony can be poisonous.

[1] http://golang.org/doc/faq#generics

-----


The FAQ merely states that generics remain an open issue. That doesn't replace a debate about it. On the contrary, it shows why a debate is necessary.

I fully understand that the Go team and long time forum dwellers are not inclined to discuss the same generics proposals over and over again. So don't!

New ideas should be welcome though.

-----


I thought Haskell did not have issues with circular data type construction with its 'tying the knot'

http://www.haskell.org/haskellwiki/Tying_the_Knot

-----


A Go templating project was posted here the other day: gotgo[0]. I haven't had a chance to use it yet, but it may alleviate some small amount of pain.

As for poor performance, that is almost certainly a result of rampant object creation, rather than reuse. Not sure how much of his program was concurrent, how sophisticated it was, etc.

Ultimately if the data set fit in memory, Python would probably be the appropriate choice for this kind of computation.

[0] https://github.com/droundy/gotgo

-----


> A Go templating project was posted here the other day: gotgo[0]. I haven't had a chance to use it yet, but it may alleviate some small amount of pain.

Replicating the C++ code generation tools of the mid-90's when templates were started to be discussed at ANSI/ISO.

-----


I'm not sure what can be said about qualifications of a programmer who doesn't know how many threads does his program run and why. And this is in Java, where the author says he's proficient. There's nothing difficult in checking how many threads are there instead of speculating on some unclear link betweeen 'final' keyword and multithreading. It's quite possible that bad performance is a result of poor implementation, not a fault of Go runtime. Unfortunately, there's no code to have look at.

-----


For fast execution of parallel processing over immutable data, I believe Scala would be an adequate choice. It would be a plus that it runs on the JVM and can easily interoperate with Java code.

-----


This guy needs to take a hard look at interfaces. Go didn't abandon generics, they just told everyone that interfaces are a better solution. You can write your code once as long as its formulated for interfaces.

As for sets, why not use a custom data structure like a balanced binary tree (such as a red-black tree)?

-----


BitSets have efficient set operations, eg: set intersection => bitwise AND, etc.

see also: https://github.com/kisielk/bigset/blob/master/bigset.go

-----


tl;dr chose wrong language for the task.

-----


there seems to be quite a few people suggesting that go is the correct choice for every task. the article is a sorely needed voice in the HN echo chamber.

personally i'm waiting for rust, go is nice but not better enough than python to justify switching - especially when you consider maturity of third-party libraries.

-----


> the article is a sorely needed voice in the HN echo chamber.

> personally i'm waiting for rust

See, this seems weird to me because Go is actually a language that you can build nice things with right now. Check out coreos's etcd[1] for example.

Rust on the other hand gets a lot of adulation in this echo chamber but is so, so far from completion that you're going to be waiting like a decade or so before you can do anything networking related with it. And personally the varying clumsy degrees to do the same thing many different ways in Rust (the various boxing and unboxing and other memory handling options) are a real turn off.

Comparing Go to Java is fair, and of course Java will come out on top given its maturity, but Go offers a lot of good things. Comparing Go to Rust is not, Rust is not ready for any kind of real world use.

[1] https://github.com/coreos/etcd

-----


you're going to be waiting like a decade or so before you can do anything networking related with it

Not true. My 'learn rust' project is pcap-based and has a trivial websocket implementation, and (after the basic learning hump) it's dirt easy. Aside from how simple it is to interact with C, Rust's current networking stack is libuv under the hood (i.e. same as node), and if you don't want libuv, native implementations are landing now.

-----


I'm guessing your websockets are not over HTTPS?

-----


No, but they probably could be, there are open-ssl bindings available: https://github.com/sfackler/rust-openssl

-----


I'm going to go ahead and be sceptical of a repo with 3 stars and more tests than working code. I doubt it works, but I didn't try it. It looks like it just wraps open-ssh libraries. It's probably going take more the 3 lines of go it takes now to create a secure wss websocket connection if you use that. I'm going to guess you'll be doing all of your own cert validations and what not once it does work.

EDIT:

It's not petty to point out that a brand new repo that doesn't look like it works, has zero documentation has been seen by a handful of people is not a good example. This is for secure code. SSL. It's pretty important to get right. This isn't a a repo for a JavaScript accordion widget. It's SSL in Rust. I'd like to see SSL in Rust. I want Rust to do well, there's nothing petty, you're reading my tone wrong. It's hard to read intention over text, assume better than you are. I've been sitting in #rust on mozilla IRC for nearly a year watching them develop the language. I'm not just catching up on the latest by reading HN.

As for jfager's a decade vs more than 3 lines rebuttal: read my other responses where I specifically qualify on using C libraries. I am going to going to go ahead and guess you haven't done much raw SSL stuff. It is a ton of work. We're not talking 5 more lines of code. We're talking thousands of lines of code, and that it will be a decade before rust catches up with go. That's just an anonymous commenter making a shitty prediction that nobody will call me out on. My point is that Rust isn't ready. Go is. Stop comparing Go to Rust. Rust doesn't work yet. Don't use it unless you want to help develop the language. All you're going to learn is how to work with a specific half implemented language that can't do basic things yet. Read my original post. I don't hate Rust, I am contrasting the HN echo chamber to love of a language that you should not be using for anything right now. This is not a controversial statement, it's right there in a big highlighted disclaimer on the rust reference manual[1].

[1] http://static.rust-lang.org/doc/0.8/rust.html#disclaimer

-----


Yes, it's just bindings to open-ssl. Yes, it's probably a little clunky to use. But we just went from "a decade or so before you can do anything networking related" to "ssl takes more than 3 lines". I can live with that.

-----


This got petty real fast.

-----


I'm interested in Rust as well, but I would guarantee we will be repeating this same trope with Rust in 2 to 3 years once people start misusing it.

-----


I have a feeling that the posts will be more "Rust is too hard" than "I used Rust the wrong way."

We'll see, though.

-----


you're going to be waiting like a decade or so before you can do anything networking related with it

Servo’s net component would like a word: https://github.com/mozilla/servo/tree/master/src/components/...

-----


> would like a word

Yeah opening up TCP connections and reading plain text http isn't hard, but there's no way to do any kind of SSL https requests with servo, which is kind of a nice thing right. And that's going to be a long long time before you ever see SSL. Have fun with those C libraries.

-----


> See, this seems weird to me because Go is actually a language that you can build nice things with right now.

i'm not denying that! in fact, i've written a couple KLOC of go code to make sure my gut feeling is right. it's a nice language and i kind of like it, but i'm much more productive in python where pretty much everything has a library written for it.

(python would certainly benefit a lot from channels/select as a langauge construct, if the GIL could be worked around.)

-----


What is really weird is how often Go and Rust are compared, period. Their designs seem to be different in almost all ways and, as you say, they don't even coincide when it comes to maturity.

-----


Go and Rust get compared because they're both new-ish and compiled and C-like. But yes, most of the time it's not really a valid comparison.

-----


Not even that, but you can't compare the main devs with Go to Rust in terms of personal accomplishment. Rob Pike who made an entire operating system at Bell Labs and has published quite a bit. Every programmer should go read Rob Pike's regular expression parser, that he wrote in like an hour and is published and annotated in the book Beautiful Code. Brad Fitzpatrick who made memcached, openid, and uh LiveJournal, Russ Cox also from Bell Labs, and many others. It's an all-star team operating under Google's demanding auspices in an ivory tower of unfathomable wealth, servers, needs and technology. These guys aren't novices, they're not going to make a shitty programming language. If you are unhappy with some part of Go (as I am actually, I'd like interfaces to know about properties as well as methods but maybe that's weird) they've probably thought about it and have a good reason for whatever choice they made.

-----


You forgot Ken Thompson, inventor of Unix.

-----


    > there seems to be quite a few people suggesting that go 
    > is the correct choice for every task.
Literally nobody has said or implied anything like this.

-----


too true, if you want a fast, simple scalable network thing then look at GO, otherwise don't.

I would also say if your handing over code to another team to support and they don't know the language and the only reason you are allowed to do it in that language is they couldn't think of any objections that you can't bypass then don't use that language!

-----


I'm really missing Erlang's awesome binary structure bit-parsing/matching/twiddling.

IMHO golang is extremely orthogonal, that it tries to live to an ideal instead of being most practical (ie generics).

btw, folks should give Elixir a shot (pun intended).

-----


Ok, so this is OT but can someone explain generics and their purpose LI5?

-----


It allows you write code that works for multiple types. For example, consider the following function in C++:

    template <typename T>
    T min(T a, T b)
    {
        if (a < b)
            return a;
        else
            return b;
    }
This code works for any type T (ints, strings, floating point numbers) that can be compared with less-than. In a language like Go that does not support generics, you would have to write a min function for ints, a different min function for strings, etc.

-----


Keeping in mind that in C++, "<" would need to be an overloaded operator defined by any type used for T. That is, to those of us non-C++ programmers, there is a function call (callback) dependency hidden in that templated function.

Not saying it's a bad thing, just that most other languages would show something like "a.compare( b) < 0" to do something like this.

-----


True, it's hidden, but the compiler will only compile code which uses that function for types which meet that condition. So yes it's hidden, but at least you'll find out about it at compile-time, not run-time, so it could be worse.

-----


If you want to model a user's transactions you can create a List<Transaction> rather than just a List, and then

- The compiler will fail to compile your code if you put anything in the list apart from a Transaction

- The compiler will fail to compile your code if you try to do anything with an object from that list which a Transaction can't do

- It also makes the code more readable as if my function takes a List<Transaction> you know what you can pass to it. Does it take a List<Transaction> or a List<TransactionId>? It's obvious.

- If you try to pass a List<TransactionId> then the compiler won't compile your code. (Otherwise you'll only find out about it at runtime.)

This means a lot fewer fails at run-time.

Which in turn means a lot less time writing (and maintaining) unit tests.

-----


In the comments he reveals that he didn't use channels. I think that's proof that he was writing Java code in Go syntax, which is not going to work out very well.

-----


You get a D in programming. (get it?)

-----


Unfortunately, D's coroutine support isn't stable like Go's one. It has unclear stack size limit, it was simply impossible to me to make a robust D program which uses coroutine. (please correct me if I am wrong.)

-----


When I code, my goal is not to find a problem that I can apply a solution on.

-----


I think in many cases you don't need generics because you can use the interface mechanism instead. The way Go does it is a bit confusing at first, so I suspect many Go newcomers don't really understand they could have used it.

As an example look into the way sorting is implemented in the standard library: http://golang.org/pkg/sort/

I had to look at this example for a long time to get it... And now I have forgotten it again since it was months ago :-(

I still thought it requires too many lines to sort stuff, but it is doable.

-----


That's effectively subtype polymorphism, while generics are parametric polymorphism. Many languages (including Java) make use of both.

-----


His dismissal of haskell is rather misinformed. Haskell has no such problems with cyclic data structures. And this:

>Except that abstracting things into functions that take the `old' graph as input, and answer the `new' graph as output are not very convenient or easy.

Is just crazy. Yes, it is very convenient and easy: http://hackage.haskell.org/package/mtl-2.0.1.0/docs/Control-...

-----




Guidelines | FAQ | Support | API | Lists | Bookmarklet | DMCA | Y Combinator | Apply | Contact

Search: