Another go at Go failed - <AUTHOR> http://oneofmanyworlds.blogspot.com/2014/01/another-go-at-go-failed.html <comment><USER3> 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://golang.org/pkg/container/)

[http://docs.oracle.com/javase/tutorial/collections/interface...](http://docs.oracle.com/javase/tutorial/collections/interfaces/index.html)

[http://docs.oracle.com/javase/tutorial/collections/implement...](http://docs.oracle.com/javase/tutorial/collections/implementations/index.html)

<comment><USER4> 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.

<comment><USER5> 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.

<comment><USER6> 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.

<comment><USER5> > 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.

<comment><USER6> _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?"

<comment><USER7> >> 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.

<comment><USER6> _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.

<comment><USER8> >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.

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

<comment><USER8> 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.

<comment><USER6> _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.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER9> 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...](http://oneofmanyworlds.blogspot.com/2011/11/draft-2-of-proposal-for- generics-in-go.html)).

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!

<comment><USER10> 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](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.

<comment><USER11> I actually wrote a bitset implementation using math/big: [https://github.com/kisielk/bigset](https://github.com/kisielk/bigset)

</comment></comment></comment><comment><USER12> 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](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 - <USER2> don't force your paying client to test it out with you or you might be one less client shortly.

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

<comment><USER12> 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.

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

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

<comment><USER16> Yet, your mobile phone calls might be going through Erlang powered switches.

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

</comment></comment></comment></comment></comment></comment></comment><comment><USER18> 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.

<comment><USER19> 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.

<comment><USER20> 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.

<comment><USER19> I think you think I'm criticising Go. I'm not. Beyond that, I think you misunderstood my response.

</comment></comment></comment></comment><comment><USER21> _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.

<comment><USER20> 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.

<comment><USER22> 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](https://github.com/thejerf/gomempool)

<comment><USER20> 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.

<comment><USER22> 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."

</comment></comment></comment></comment></comment><comment><USER23> 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.

<comment><USER24> 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.

<comment><USER25> [http://upload.wikimedia.org/wikipedia/commons/9/94/Gartner_H...](http://upload.wikimedia.org/wikipedia/commons/9/94/Gartner_Hype_Cycle.svg)

<comment><USER26> 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... :)

</comment></comment></comment></comment><comment><USER27> 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.

</comment><comment><USER28> _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.)

<comment><USER20> 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.

<comment><USER29> _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.

</comment></comment></comment><comment><USER22> 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)

<comment><USER30> 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.

<comment><USER31> 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.

<comment><USER30> > 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?

</comment></comment></comment></comment><comment><USER32> 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?

</comment><comment><USER33> 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.

<comment><USER34> 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).

<comment><USER33> 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.

</comment></comment></comment><comment><USER35> 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.

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

<comment><USER16> 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.

<comment><USER36> 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 :-)

</comment></comment></comment></comment><comment><USER37> 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.

<comment><USER38> Wouldn't that mean an extra level of indirection while dereferencing?

<comment><USER39> Yes, but so does run-time generics somewhere along the line.

<comment><USER40> 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...](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html)

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

<comment><USER38> 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.

</comment></comment></comment></comment></comment></comment><comment><USER41> 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/](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.

</comment><comment><USER42> 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.

</comment><comment><USER43> 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.

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

<comment><USER45> 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.

<comment><USER44> [http://golang.org/doc/faq](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.

</comment></comment></comment></comment><comment><USER9> 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.

<comment><USER46> Did you by chance profile the Go program to see where the hot spots are?

</comment></comment><comment><USER47> 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!!"

</comment><comment><USER48> 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](http://chrisdone.com/posts/dijkstra-haskell-java)

<comment><USER30> 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.

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

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

</comment></comment></comment></comment><comment><USER49> 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.

</comment><comment><USER50> > 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.

<comment><USER51> probably this: [http://research.swtch.com/generic](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)

<comment><USER50> Hm. Which of these does C# use? Which does Haskell use?

<comment><USER16> 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.

<comment><USER50> 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.

<comment><USER16> 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.

</comment></comment></comment></comment></comment></comment><comment><USER52> 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?

<comment><USER36> 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.

<comment><USER52> 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.

<comment><USER36> 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.

</comment></comment></comment></comment><comment><USER53> 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.

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

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

</comment><comment><USER56> > 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.

</comment><comment><USER57> $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.

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

<comment><USER57> 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.

</comment></comment></comment><comment><USER59> 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](https://gist.github.com/mediocregopher/8319986)

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

</comment><comment><USER60> 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](http://www.haskell.org/haskellwiki/Tying_the_Knot)

</comment><comment><USER61> 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.

</comment><comment><USER62> 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](https://github.com/droundy/gotgo)

<comment><USER16> > 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.

</comment></comment><comment><USER63> 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.

</comment><comment><USER64> 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)?

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

see also: [https://github.com/kisielk/bigset/blob/master/bigset.go](https://github.com/kisielk/bigset/blob/master/bigset.go)

</comment></comment><comment><USER66> tl;dr chose wrong language for the task.

<comment><USER58> 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.

<comment><USER67> > 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](https://github.com/coreos/etcd)

<comment><USER68> 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.

<comment><USER67> 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.

<comment><USER69> You forgot Ken Thompson, inventor of Unix.

</comment></comment></comment></comment></comment></comment><comment><USER70> 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).

</comment><comment><USER71> Ok, so this is OT but can someone explain generics and their purpose LI5?

<comment><USER72> 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.

<comment><USER29> 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.

<comment><USER73> 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.

</comment></comment></comment></comment><comment><USER74> 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.

</comment><comment><USER75> You get a D in programming. (get it?)

<comment><USER76> 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.)

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

</comment></comment></comment><comment><USER77> _" 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.

<comment><USER78> 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.

<comment><USER77> 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).

<comment><USER78> 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.

<comment><USER79> 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).

<comment><USER78> 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.

<comment><USER80> 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](http://golang.org/doc/faq#generics)

<comment><USER78> 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.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER81> 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/](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.

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

</comment></comment><comment><USER82> 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-188.8.131.52/docs/Control-...](http://hackage.haskell.org/package/mtl-126.96.36.199/docs/Control- Monad-State-Lazy.html)</comment>


How to pick a random number from 1-10 - <AUTHOR> https://torvaney.github.io/projects/human-rng <comment><USER2> There is a simpler solution if you do not mind leaving entropy on the table. Break the people up into groups of two without regard for their selection. If two people provide the same number, ignore them. Otherwise, output "0" if the first person's number is smaller then the second, and output "1" if the first person's number is larger.

From this, you have a sequence of uniformly random bits, from which you can construct a uniformly random number between 1 and 10. A simple way (although, again, likely leaving entropy on the table) is to break these bits into groups of 4; interperate them as 4 bit unsigned integers, and discard any result that is not in the range 1-10.

<comment><USER3> That works and is perfectly uniform (if the people are i.i.d.), but requires quizzing around 20, 40, 60 or more people for a number before you can deliver one, while the algorithm described only requires one or two.

EDIT: Not quite that many, more like around 9, 18, 27 or so, see below.

<comment><USER4> Parents algorithm always works, the one described has a massive failure mode - people slowly learn that they are likely to say 7 and self-censor by picking another number. Or maybe in a different culture the distribution changes (say China and the numbers 4, 8).

<comment><USER5> I would guess that in China the probabilities of 4 and 8 goes down. Asking people to pick randomly drives them away from special numbers.

<comment><USER6> In the US 7 is a lucky # and a statistical outlier in that it was more frequently chosen in the article above.

<comment><USER5> You might be right, but my guess is that 7's reputation for luck isn't famous enough to make a difference, and in fact it's common because other numbers seem too "unrandom".

We could test by asking people to pick numbers less than 100. I bet people would focus on odd numbers, especially those greater than 50, not ending in 5 or not having both digits the same.

<comment><USER7> I decided to do that.

Data and light analysis is here: [https://docs.google.com/spreadsheets/d/1Dh0wiTCRkBhckWGXtjZg...](https://docs.google.com/spreadsheets/d/1Dh0wiTCRkBhckWGXtjZgI_7CX1ZEbqbw4d1KACt8CdU/edit?usp=sharing)

I definitely overpaid on Mechanical Turk per response, given how lightning quickly the data came in. (I decided to pay $0.10/HIT for 50 responses and got 68 responses in 8m26s.) I suspect that offering a nickel would have gotten the survey filled in under half an hour still...

<comment><USER6> Maybe 7 cents?

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER8> ...or just add up the answers mod 10.

This has the property that if even a _single person_ answers uniformly at random, then the final number you compute will be uniformly random, regardless of how everyone else answers.

<comment><USER9> > ...or just add up the answers mod 10.

This is how my board game groups pick the first player.

<comment><USER10> But if you're playing a board game, don't you already have dice at hand?

<comment><USER9> It depends which game, many do not use dice.

</comment></comment></comment></comment><comment><USER11> Am I missing something, or is this a textbook case of overfitting? It's a neat project, but at the bottom he prescribes what to do if the person says 1-3, or if they say 4 or 5, etc. Therefore, it's completely overfit to the Reddit data at the top.

<comment><USER12> Overfitting typically happens when the number of training samples is small compared to the number of parameters of the model. It especially happens when the input space is high-dimensional.

Here the input space has a only one dimension. The model has 10 parameters. There are 8500 samples. So, the author safely assumes that no over-fitting occurs.

<comment><USER13> Wrong. You are assuming a good selection over the whole search space of humans. If you took HN I bet you would get a different distribution. The Reddit data only applies to sampling Redditors sampled using similar strategies, the generalization is limited by how general the collection strategy was

<comment><USER12> Yes, there is a possibility that the sample is biased. But that does not matter for this experiment.

The OP says that the model should be built with people in the same room than him, and then the human RNG should be executed with the same people.

As a consequence, OP has to capture the bias of the people in his room to make his RNG work.

The model would break only if the people in the sample change their strategy to pick random numbers after some time.

The data from Reddit is just used as an example of how to make a human RNG from redditer random picks.

As long as the training and testing are done from the same group of people, there is no issue, even if this group is biased.

Moreover, I don't see any prior reason to believe that redditors and HN readers would have different biases. That would be an interesting experiment, though. However, the predominance of the number 7 in article's data might be a western culture thing.

</comment></comment></comment></comment><comment><USER14> > The easy thing to do is to ask someone "Hey, pick a random number from 1 to > 10!". The person replies "7!".

Seven factorial is way bigger than 10. Just kidding, sorry.

But what I was actually going to say was, when I read the title of the post, before clicking through, I decided to think of a number myself and I chose the number seven. So it was fun to see that same number in the article.

10% chance in theory and in reality it's about 25% likely for someone to pick the specific number I did. If only the odds in the lottery were this good.

Why, by the way, is it that seven is so popular?

<comment> another-dave From the Reddit comments someone wrote:

"Can't have the evens, they aren't random. 1 and 9 are too close to the outside. 5 isn't random, it's right in the middle! 3 is too low. Leaving 7"

It does feel like the type of biased logic that would run through your mind in the moment — interesting to think, if we have such 'fallacies' on simple stuff, what level of blindspots do we have on more complex split-second decisions.

<comment><USER15> Quite a few, anchoring is pretty interesting and can often be completely subconscious.

</comment></comment></comment><comment><USER16> There is a simple way to generate random numbers in your head: [https://groups.google.com/forum/#!msg/sci.math/6BIYd0cafQo/U...](https://groups.google.com/forum/#!msg/sci.math/6BIYd0cafQo/Ucipn_5T_TMJ)

<comment><USER17> For ease of reference, here is the text at that link verbatim:

Choose a 2-digit number, say 23, your "seed".

Form a new 2-digit number: the 10's digit plus 6 times the units digit.

The example sequence is 23 --> 20 --> 02 --> 12 --> 13 --> 19 --> 55 --> 35 --> ...

and its period is the order of the multiplier, 6, in the group of residues relatively prime to the modulus, 10. (59 in this case).

The "random digits" are the units digits of the 2-digit numbers, ie, 3,0,2,2,3,9,5,... the sequence mod 10. The arithmetic is simple enough to carry out in your head.

This is an example of my "multiply-with-carry" random number generator, and it seems to provide quite satisfactory sequences mod 2^32 or 2^64 , particularly well suited to the way that modern CPU's do integer arithmetic.

You may choose various multipliers and moduli for examples of random selection of the types you ask about.

A description of the multiply-with-carry method is in the postscript file mwc1.ps, included in

The Marsaglia Random Number CDROM with

The DIEHARD Battery of Tests of Randomness,

available at

[http://stat.fsu.edu/pub/diehard/](http://stat.fsu.edu/pub/diehard/)

George Marsaglia

</comment></comment><comment><USER18> I usually just look at my watch and use the last digit of the seconds value. 0=10

reasonably random

<comment><USER19> Very easy to predict.

<comment><USER18> how so? if you ask me for a number from 1-10 and I use my watch, how do you have any predictive information? Even if you looked at your watch there is no reason it should have the same seconds value as mine.

Obviously this is not really something you could automate and if you were to use a clock on an ongoing basis you might be able to predict likely numbers, but that was not in the original scenario.

<comment><USER20> Ah but there _is_ a reason for my watch to have the same seconds value as yours, and that is if our watches are kept synchronized to an accurate time source, for ex. via NTP. By assuming otherwise you're sidestepping the problem by claiming you already have a reliable RNG.

Heck, even granted you have an unsynchronized watch, your "random" numbers are easy to predict, I'll ask you for a random number once per second and after a few answers I don't need to ask any more to know your answer.

<comment><USER21> This is an example of a precise analysis that is unhelpful because it is irrelevant in the contexts in which the algorithm would be used. It's like saying "all algorithms are constant time-complexity in practice because computers are finite". True but useless.

</comment></comment></comment></comment></comment><comment><USER22> If I had to generate a random number I would do this:

As I ask each person I cycle a secret number through 0-9 in my head. (I increment mod 10 after I ask each person)

When I ask I get their answer, I secretly add my secret number modulo 10 (and consider 0 === 10) and record this in secret.

Then record a tally for each number, the one with the most wins.

This assumes the asked people will not know or guess my internal number. So I seed based on the first person's number (OK they know!) but everyone else wont.

Edit: someone came up with a simpler solution: [https://news.ycombinator.com/item?id=20315835](https://news.ycombinator.com/item?id=20315835)

</comment><comment><USER23> How about not using 'pick a random number from 1-10' as the source of entropy? For example, have everyone (from a group of some size) select a natural language sentence of 5 words or more, sum the ASCII values of the upcased alphabetical characters of everyone's sentences, and take the last digit (then add one).

</comment><comment><USER24> This looks to be the discrete random variable problem with the alias method:

[https://en.wikipedia.org/wiki/Alias_method](https://en.wikipedia.org/wiki/Alias_method)

but they don't seem to reduce each choice (1-10) to just two options.

</comment><comment><USER25> Put everyone in a numbered sequence unknown to them. Add their chosen number to their sequence number, mod 10.

This re-maps everyone's choices so they actually have no idea what number they are actually choosing and efficiently redistributes the bias in their choices without massively complicated functions. It is also robust to changes in the distribution pattern. However it would only work well if you had at least 10 people and the number of people is divisible by 10.

<comment><USER26> Wouldn't putting "everyone in a numbered sequence unknown to them" require a random number, which we don't have?

<comment><USER27> > Wouldn't putting "everyone in a numbered sequence unknown to them" require a > random number, which we don't have?

Yes. The above answer just obfuscates the issue. Consider ten people overwhelmingly biased towards 7. The suggested approach in all likelihood gets you 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Then what? You're clearly not much closer to getting a single random number without a random way of picking one of them.

<comment><USER25> >You're clearly not much closer to getting a single random number without a random way of picking one of them.

That's a characteristic of the original formulation of the question, not specifically in my solution. It's implicit in the article that you can choose an arbitrary person in the room without bias.

<comment><USER27> It's a shortcoming specifically introduced by your proposal. If you've got a random way of picking one of ten people, then you've already got a random number between one and ten. Your answer essentially reduces to: ask one person to think of a number then add an actual random number and mod 10.

<comment><USER25> From the article:

>The easy thing to do is to ask someone "Hey, pick a random number from 1 to 10!". The person replies "7!". Great! Now you have a number. However, you start to wonder, is the number uniformly random?

So the problem reduces to transforming one form of randomness (picking a person) to another form (a uniform numeric distribution. That's implicit in the whole rest of the article.

>If you've got a random way of picking one of ten people, then you've already got a random number between one and ten.

You've got a source of randomness, but you still need to turn that into a number. The article gives one method and I've given another. You could also assign the people numbers from a stack of shuffled numbered tiles, then pick a person although that requires you have the tiles which is not really part of the setup. The conceit is that you have to use people's ability to pick numbers pseudo-randomly. There are probably numerous ways.

</comment></comment></comment></comment></comment></comment><comment><USER28> How about 1 person labels 10 people 1 thru 10 and another person not knowing how they're labeled chooses 1 of those people

edit: the first person labels the 10 in a jumbled up way, then the 10 people not knowing how they are labeled then jumble themselves up

<comment><USER29> This seems like it could work pretty well. It would be interesting to try it out.

I see two possible sources of bias:

1\. The way in which a person labels the others won't be random. And multiple people may exhibit the same pattern. For example, let's say that people are biased towards trying to label an "average" person as #1. This might be based on height, weight, attractiveness, etc. Then a given person may have an uneven distribution of labels attached to them. Further compounding this could be that the most "average" person is the one most likely to be chosen by the second person.

2\. You would need to come up with a random way to pair up the first and second person. The worst case might be that the same two people are always paired with each other, and each person always chooses the same person in the room. Then you would end up with a series of 10 digits repeating themselves.

<comment><USER28> i don't know how strict it is with having no props. i think a blindfold could be acceptable because it can be used from the materials of the people in the room but i don't know about actual labels (maybe post-it notes) or a marker pen. so the first person can't see the people and can only like touch their back to put the label on.

edit: but then it gets to where you may as well just put the numbers in a hat :P

</comment></comment></comment><comment><USER30> Top poker players have mental models for generating random numbers at the table, to avoid predictable play. I can't find any link, but it doesn't require a room full of people (or a wristwatch).

</comment><comment><USER31> 0-9: Look at the second hand on your watch, what is the last digit?

odd/even or heads/tails: is the seconds odd or even?

<comment><USER32> I bet that has sample bias as there's a small amount of choice in when they reply

<comment><USER33> Only if they know the time.

For binary selection, keep the watch and tell them to make an indication (say something) in a few seconds. Note down whether the seconds were even or odd, then hand them the clock and swap roles. Keep the watch hidden until the moment you need to inspect it; record the time as soon as you can see the watch. Merge the two notepads to get the final stream of randoms.

For last digit of seconds, wait a few minutes between each query (making sure they can't see the clock during the rest period). "A few minutes" is imprecisely measured by you, who does not have access to a clock. They delay would foil any attempts at them keeping track of the time in their head. Bonus for distracting them to help with that. And instead of asking them for the last digit, have them flip the watch and then record the time that you [both] first saw.

</comment></comment></comment><comment><USER34> The general method illustrated here (rearranging a sufficiently uniformly distribution over 100 into a very-close-to-uniform distribution over 10) is a special case of a topic in information theory called randomness extraction:

[https://cs.haifa.ac.il/~ronen/online_papers/ICALPinvited.pdf](https://cs.haifa.ac.il/~ronen/online_papers/ICALPinvited.pdf)

[https://people.seas.harvard.edu/~salil/pseudorandomness/extr...](https://people.seas.harvard.edu/~salil/pseudorandomness/extractors.pdf)

The problem being solved is trying to obtain a distribution arbitrarily close to uniform from sampling a known random distribution.

</comment><comment><USER35> Maybe an easier solution would be to append all the answers, take a hash (e.g. sha1), then convert the last 2 digits from hex to decimal, and mod 10.

1 liner.

\--

EDIT: I lied, this doesn't work, it biases towards 1-5. I guess you could convert to decimal, and divide by (FFFFFFFFFFFFF / 10)

<comment><USER36> "But, let's say you have to do this without access to coins, computers, radioactive material, or other such access to traditional (pseudo) random number generators. All you have is a room of people."

Can you do a SHA1 in your head?

<comment><USER37> Not quite in his head, but Ken Shirriff did SHA-256 with pencil and paper:

[http://www.righto.com/2014/09/mining-bitcoin-with-pencil- and...](http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and- paper.html)

</comment></comment></comment><comment><USER38> A few years ago I was stumped by a similar question about generating uniformly random numbers with less than ideal constraints. The helpful minds at MathOverflow solved it [0] but it wasn't something that you could guarantee would always work. (The question explains in more detail... Due to the miniscule probability of a never ending sequence of less than ideal random integers.)

I'm curious whether this technique could be applied to my original problem!

[0]: [https://math.stackexchange.com/q/1273214/196899](https://math.stackexchange.com/q/1273214/196899)

</comment><comment><USER39> You could use the biased distribution to build a lookup table for a less biased distribution.

Build a 10^n lookup table with an entry for each of the possible (ordered) n-tuples of values, give each entry a weight of the product of the probabilities of each of the n values making the entry.

Create a set of probabilities for each output and initialise to zero, run through each of the generated tuples in descending order of weight, set the lookup value to the output with the current lowest probability (or the first, or feed in another PRNG - but you have to stop somewhere) and increase the probability according to the weight associated with the tuple.

At the end of this process you'll have a PRNG that's at least as good as the input (and generally better) - although you'll need to query the seed PRNG n times per result. The higher the value of n the better the output (Although the lookup table will become quite large).

<comment><USER39> This solution gives no consideration to security only the distribution of outputs.

</comment></comment><comment><USER40> There's no need to solve the distribution balancing problem with linear programming. You can just use a greedy algorithm where you repeatedly give probability mass from numbers with more than 10% to numbers with less.

</comment><comment><USER41> In similar situation (we were playing RPG while on a trip, and we needed to "throw dice") - we simply had the DM count silently and the player that was "throwing" say "STOP".

It was pretty much uniform.

</comment><comment><USER42> Or have them give the last digit of the age of their oldest living family member.

<comment><USER43> Due to the distribution of people's age towards the "old" end of the scale, I'd guess that this is more likely to be 0 than 9?

<comment><USER44> Yeah, I'm curious to look at data, but I think this will be skewed towards lower digits.

</comment></comment></comment><comment><USER45> > Ideally we want to preserve as much of the initial distribution (i.e. do as > little chopping and changing) as possible.

I was thinking through the post that this sounds like a straightforward problem and it is: [https://stackoverflow.com/a/5953133/86433](https://stackoverflow.com/a/5953133/86433)

Except the introduction of an "ideally" optimization condition turns it from a straightforward transform into something requiring a linear programming solver. I wonder if the resultant algorithm is actually any simpler though...

</comment><comment><USER46> The interesting part is the recursive application of the algorithm. I'm wondering why it isn't applied fully recursively but only up to one step. Surely, if the algorithm can generate a uniform probability distribution, it can also generate an arbitrary probability distribution, so why not use that arbitrary probability distribution in order to generate the uniform probability distribution?

</comment><comment><USER29> If you have a pair of scissors or are willing to ask people to take a brief bit of pain...

Hair.

Cut (or pull) off a chunk of hair from everyone in the room. Put in a big pile. You'll have hundreds of thousands of hairs. It will be a glorious mess :)

Now ask people in the room to grab a handful of the hairs and count them. Take the last digit of the each count - there's your random number. You could maybe get multiple digits from a single handful - just be aware of Benford's law.

</comment><comment><USER47> So this relies on that being a somewhat normal distribution (7 being the most common number).

What if the people were primed by the first person saying 7? What if the first person had said 3?

So really you'd need to get your 'random' numbers, check the distribution, than redistribute your 'random' numbers. Which doesn't seem random or 'random' to me.

</comment><comment><USER48> The 8500 students are numbered off (assigned id's) from 1 to 10. Then you wait. Your first random number is the ID of the first person who dies. Second random is the ID of second person to die. Etc.

Fairly slow algorithm. And only good for 8500 random numbers. But I think it would give a good distribution.

</comment><comment><USER49> I actually laughed out loud when I saw the image of the human RNG distributions. 7 is a random number. Who knew?

<comment><USER50> I feel like you could probably 'fix' it by the following protocol:

1\. Ask your participant to write down a random number. 2\. After they've written that number down, inform them you will guess at their number, and give them a dollar if you guess wrong. 3\. Ask if they'd like to change their random number. 4\. Allow them to write down their new number.

The before/after would probably change the distribution, and pretty much demonstrate that people can be more random when motivated.

<comment><USER51> I'm sure the distribution would change, but not sure it would be closer to uniform. It's now a completely different problem: choose a number most resistant to guessing. For example, if the participant hypothesises that your guess will be a "random" number chosen by you, she should always pick 10.

</comment></comment></comment><comment><USER52> If you can widen the answers the people can give you could first determine the distribution of a larger width (i.e., pick a number from 1 to 100) then map those to the 1-10 distribution based on their frequency.

This is effectively the same as the person proposing sampling tuples.

</comment><comment><USER53> This can be generalized to having any distribution, simulating a die:

[http://www.keithschwarz.com/darts-dice- coins/](http://www.keithschwarz.com/darts-dice-coins/)

</comment><comment><USER7> Survey for analysis on this thread:

[https://www.surveymonkey.com/r/XWML9JM](https://www.surveymonkey.com/r/XWML9JM)

<comment><USER7> Data (including a batch I paid for on Mechanical Turk):

[https://docs.google.com/spreadsheets/d/1Dh0wiTCRkBhckWGXtjZg...](https://docs.google.com/spreadsheets/d/1Dh0wiTCRkBhckWGXtjZgI_7CX1ZEbqbw4d1KACt8CdU/edit?usp=sharing)

(Amusingly, "69" is an over-represented response...)

</comment></comment><comment><USER54> This assumes independent events. If someone picks 7 and you ask them for another random number, it is highly unlikely (certainly not 28.1%) that they will pick 7 again.

<comment><USER55> "Ask _another_ person for a random number"

</comment></comment><comment><USER56> So you need access to a uniform RNG to implement this as it takes the human bias and multiplies by a factor and the RNG... so why not just use the uniform RNG?

<comment><USER57> You do not need access to a uniform RNG for this - he uses more humans to get the redistribution chance.

</comment></comment><comment><USER58> You could use the month of birthday as random source,if it is bigger than 10,then ignore.

</comment><comment><USER59> Use the middle square method:

[https://en.wikipedia.org/wiki/Middle- square_method](https://en.wikipedia.org/wiki/Middle-square_method)

It can be trivially calculated with pencil and a paper and will be random enough. You just need to pick a seed and off you go.

If it was good enough for Von Neumann it is good enough for you.

</comment><comment><USER60> Didn't the world agreed already that the new Pseudocode Language was Python?

</comment><comment><USER61> What number are people most likely to pick the second time if you ask them twice?

<comment><USER62> Maybe the most likely number of the ones they haven't picked? So 5 if you picked 7 and 7 if you picked anything else. This should be tested.

</comment></comment><comment><USER63> Or just carry a coin-like flippable object. (Cell phone?)

<comment><USER29> And if no objects are allowed in the room at all, then pick the lightest person and flip them :) Though flipping a person multiple times is difficult, so it could be biased towards 1 flip.

</comment></comment><comment><USER64> Or just use digits of pi; most people have at least 10 digits memorized, some have 20+ memorized. There's also a formula you can memorize for calculating the nth digit of pi, so you have infinite random numbers without memorizing an esoteric algorithm with a bazillion corner cases.

That said, I still thought this was an interesting article and I loved the animated bar graphs.

<comment><USER65> Most people have _at least_ 10 digits memorized? That is one bold claim

<comment><USER64> I meant here on Hacker News. I would guess most of us here played with our TI-83s enough to know the first 10

<comment><USER66> I wonder how many people on HN have even seen a TI-83, I don't think I've seen one since I sold mine when I finished the Danish equivalent of high school in 99. I mean, they were apparently discontinued in 2004, that's 15 years ago.

<comment><USER67> In the US TI has established a multi-decade monopoly in schools. Basically, the teachers are only familiar with specifically them, so they require student only use them, so new teachers are only familiar with them.

As a result, a new TI-85 equivalent is only trivially upgraded from what I used 25 years ago and costs exactly as much minus inflation.

<comment><USER66> Wow, why aren't students using laptops?

<comment><USER67> In college some students use laptops for taking notes. Not so much in high school. But in both during tests, electronics are strictly regulated to prevent cheating. Teachers know how to factory reset TI calculators. So, they and only they are allowed. Also, teachers know how to instruct how to use TI calculators. So, they are sometimes even required for certain classes.

<comment><USER68> Lol in Germany i was only ever allowed to use non-programmable calculators all the way through high school, college, university.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER69> It's not random if you're forcing it to be uniform. May as well skip the math and do this instead:

Divide all the people into groups of 10. Have the members of a group play each other at whatever, e.g. arm wrestling, to produce a rank from best to worst. Their rank becomes their answer.

Now everyone will reply with a number as close to uniform as the total number of people is divisible by the number of choices.</comment>


Where do Google's flaky tests come from? - <AUTHOR> https://docs.google.com/document/d/1mZ0-Kc97DI_F3tf_GBW_NB_aqka-P1jVOsFfufxqUUM <comment><USER2> Not at Google, but making reliable tests was one thing I really struggled with professionally. There are many, many possible causes of non-determinism. Even something as simple as using multiple threads means that you suddenly realize that you must decide how long you're willing to wait for the other thread to complete. (You always kind of did, but when all the logic was on one thread, the waiting was not as obvious and errors were less likely to cause hangups.)

Unfortunately, under high load, I found that threads can be starved of CPU for seconds at a time. The CI machine was flooring it trying to build the software and run the tests. Setting the timeout high enough that there were no random failures caused by CPU starvation meant that build failures would take a very long time, delaying feedback for errors. That was nearly as bad as the flakiness.

I mostly fixed the flakiness by making the number of threads configurable and only running one thread in the testing environment, but I think a better way would be to reduce the number of parallel jobs to keep the test machines' CPU utilization rate at something more reasonable. Then, you can set timeouts that reflect real performance expectations for your software.

<comment><USER3> When doing anything concurrently and/or in parallel, it is always good to have an input queue and an upper bound on the number of tasks (/threads/processes/...). Also an asynchronous flow.

You need to handle other problems (back-pressure, priorities, timeouts, ...) but if you need it you need it.

<comment><USER4> But how do you go about creating tests for all of that?

<comment><USER5> You don't need to write your own and test it -- use something like GNU parallel (if your tests can be run individually as commands or shell scripts) or a test framework that supports parallelism.

</comment></comment></comment></comment><comment><USER6> This document is getting absolutely decimated. Why did OP post this without putting in some moderation controls first?

Edit: I found the actual engineering blog post that this google docs ended up turning into. It's probably going to be a easier read from here I imagine - [https://testing.googleblog.com/2017/04/where-do-our-flaky- te...](https://testing.googleblog.com/2017/04/where-do-our-flaky-tests-come- from.html#comments)

<comment><USER7> wow lol! Watching 63 people making realtime changes to the same doc is crazy lol.

<comment><USER8> lol, it's pretty funny

<comment><USER9> not really. it's just jerks being vandals to show that they can.

</comment></comment></comment></comment><comment><USER2> Original blog post (non-wiki version): [https://testing.googleblog.com/2017/04/where-do-our-flaky- te...](https://testing.googleblog.com/2017/04/where-do-our-flaky-tests-come- from.html)

Previous discussion: [https://news.ycombinator.com/item?id=14146841](https://news.ycombinator.com/item?id=14146841)

</comment><comment><USER10> But of course larger tests are flaky. They have more lines of code. That's practically the null hypothesis, where you assume every line of code has a certain chance of flaking, and then you just multiply out all the probabilities.

I was expecting some in depth analysis, like "tests that use time libraries are flaky" or "tests that have callbacks are flaky" or something. This doesn't really make any headway towards understanding the problem.

<comment><USER11> >where you assume every line of code has a certain chance of flaking, and then you just multiply out all the probabilities.

This assumption doesn't make much sense though. `y = x + 1` shouldn't flake. Nor is your comment here a correct reflection of "size". Size in the article means time the test runs or amount of memory used (ie. constructing a larger SUT), not LoC. Edit: I'm partially mistaken, one measure of size is binary size, which should be generally correlated with LoC, though not absolutely. Webdriver tests which use image/video goldens are an example where test size may not correlate with LoC at all.

>This doesn't really make any headway towards understanding the problem.

The second part of the article does address exactly this (webdriver tests are correlated with flakyness, although they're also larger by virtue of needing to spin up a headless browser, which has a memory cost).

More edit:

As someone who has written and heavily deflaked some (very large) tests using, I believe, the "internal testing framework" mentioned in the article, flakyness always appeared as a tradeoff with speed. Parallelizing tasks introduces a level of randomness which can lead to flakes. Short(er) timeouts on things that can have long 95 or 99th percentile latencies, etc. It can sometimes be worth it to have a test flake some small percentage of the time instead of waiting longer (granted this is also often a flaw in test design somewhere).

But when you're testing a big system with many moving parts, it's not uncommon to have something that takes 30 seconds 95 or 99% of the time, and every once in a while 5 minutes. The question is if its worth it to keep extending your timeouts for n-sigma events, especially since that means that when your tests are _actually_ broken, they'll potentially take much, much longer to complete. You can lower the false false negative rate, but the cost is that true negatives become much more expensive to compute. Is that worth it? It depends.

<comment><USER12> It's probably worth noting that

        y = x + 1

will flake out if x is an int, and it's value is INT_MAX.

<comment><USER11> I'm pretty sure it will still act consistently. Under the same compiled binary (which a hermetic environment enforces), the undefined behavior will be consistent from run to run, since the same optimizations will be used.

That's not true in a theoretical sense (undefined behavior allows me to rewrite signed overflow to "return 7 with some probability, and `rm ~/` otherwise"), but for any modern compiler, I'd assume that the optimizations chosen where signed overflow is undefined don't involve randomness.

<comment><USER12> It will act consistently if the value of x is consistent. If it's not, then it could flake out on that line.

<comment><USER11> If the value of x is inconsistent, you had flakyness somewhere else.

That line will always act consistently, modulo solar radiation.

</comment></comment></comment></comment></comment></comment><comment><USER13> That was underwhelming. I was hoping for some analysis of the statistics of causes, not just "more code can contain more bugs". I've fought the flaky test battle a lot at work and written a few articles that all contain more information and mitigation strategies that I've used:

[https://medium.com/@boxed/use-the-biggest- hammer-8425e4c7188...](https://medium.com/@boxed/use-the-biggest- hammer-8425e4c71882) [https://medium.com/@boxed/intermittent-tests-aligned- primary...](https://medium.com/@boxed/intermittent-tests-aligned-primary-keys- dcf14953d9af) [https://medium.com/@boxed/flaky-tests-part-3-freeze-the- worl...](https://medium.com/@boxed/flaky-tests-part-3-freeze-the- world-e4929a0da00e)

</comment><comment><USER14> Here is Mozilla's list of common causes for flaky Firefox tests (aka "intermittent oranges"):

[https://developer.mozilla.org/en- US/docs/Mozilla/QA/Avoiding...](https://developer.mozilla.org/en- US/docs/Mozilla/QA/Avoiding_intermittent_oranges)

<comment><USER15> Those are interesting but very JS centric (though some principles apply regardless)

Of the tests I've seen, one usual source of flakyness is ignored side-effects between tests (DB is not emptied, some source of persistence is not reset - could be a 'global' variable or _a mock library not mocking things correctly_ ), sometimes import conflicts (some module clashes with a builtin library, but if you do this in a certain order it works)

Other sources include people using the equivalent of "now()" but then you're on those small time periods where your assumptions break (for example, now() is the last day of the year and you're assuming tomorrow is still in the same year, things like that)

</comment></comment><comment><USER16> If you can manage to get an editing slot (Google docs hard caps the number of simultaneous editors) the amount of suggested vandalism this already has is amazing. It also gives an interesting view in to what people are feeling about Google's level of testing.

Here is a preview: [https://cdn.pbrd.co/images/HZfekkKc.png](https://cdn.pbrd.co/images/HZfekkKc.png)

<comment><USER11> And if you want to see the unmangled article: [https://docs.google.com/document/d/1mZ0-Kc97DI_F3tf_GBW_NB_a...](https://docs.google.com/document/d/1mZ0-Kc97DI_F3tf_GBW_NB_aqka-P1jVOsFfufxqUUM/preview)

</comment></comment><comment><USER17> Watch a document get vandalized in realtime. Fun.

<comment><USER18> IKR, realtime Wikipedia brought to you by multiplayer EtherPad. With multiplayer word highlighting!

</comment></comment><comment><USER9> Unfortunately, Redditors and HN members are destroying the document, because they think it's funny.

The pre-destroyed document can be found here:

[https://docs.google.com/document/d/1mZ0-Kc97DI_F3tf_GBW_NB_a...](https://docs.google.com/document/d/1mZ0-Kc97DI_F3tf_GBW_NB_aqka-P1jVOsFfufxqUUM/edit#heading=h.ec0r4fypsleh)

<comment><USER19> I hate Google docs like this because I just want to see it but I can't without "requesting permission" which means someone knows exactly who I am.

<comment><USER9> we used to be able to until redditors and hn people decided to ruin it

</comment></comment></comment><comment><USER20> """Google has around 4.2 million tests that run on our continuous integration system"""

On how many lines of code? Just wondering how big google is LOC wise?

</comment><comment><USER21> Shouldn't the developers be falling over themselves to fix all those flaky unit tests? I can't believe Google just lets them keep running unfixed. In my code, I don't check anything in unless all unit tests pass (without flaking).

<comment><USER22> How many times do you run the tests? I've had tests that only fail about 1/200 times or less.

<comment><USER21> If someone showed me that my tests were not deterministic, I'd be in a hurry to figure out why. Hidden race conditions? Unreliable initial state of the system? Unexpected interactions between tests? I'm just surprised that this article doesn't mention any effort to find the root cause and fix it.

<comment><USER23> The challenge isn't when _your_ tests are flaky. The challenge is when a test written by some guy who left the company begins flaking, and your preliminary investigation shows it's a timing issue two layers below you in the stack, but the people who own that project insist you're using it wrong and your test shouldn't pass in the first place. It's hard to sell why your team should drop everything to untangle that knot.

<comment><USER24> These are all just excuses, and common ones at that. Think of it this way:

* The test cases written by the some guy who left the company _are now your test cases_.

* Before he left the company, he was able to commit the test cases, passing whatever review / quality processes were put in place by the company (or that the company failed to put in place).

* If your team wants to have the benefit of reliable testcases, the knot needs to be untangled. That doesn't entail "dropping everything" (although perhaps thats the only way your organization knows how to operate), there is no reason that improving test cases can't be prioritized alongside and in the context of other work.

Unfortunately, in my experience it's usually the last bullet point where things fall down. Product owners consistently pressure development teams to deliver features _now_ , and do test cases _later_ , which means _never_.

<comment><USER23> The last bullet point often should fall down. There are a lot of tests that aren't worth the effort of making them run reliably, but most organizations have (understandably) strong norms against fixing a failing test by removing it.

</comment></comment></comment></comment></comment></comment><comment><USER25> (2017) (I was pretty sure I already read this)

</comment><comment><USER26> Warning: requires logging into google to read post!

You can read the original post without the "paywall" here: [https://testing.googleblog.com/2017/04/where-do-our-flaky- te...](https://testing.googleblog.com/2017/04/where-do-our-flaky-tests-come- from.html)

</comment><comment><USER27> tl;dr-

1\. Larger tests are more flaky

2\. Choice of tech has additional, minor contributions to flakiness (eg. unit tests vs. webdriver vs. Android emulator)</comment>


Monads Categorically - <AUTHOR> https://bartoszmilewski.com/2016/12/27/monads-categorically/ <comment><USER2> I have read many monad tutorials. I acknowledge the elegance.

Would someone meet me halfway though and describe to me a specific pragmatic task that a monad accomplishes...and, most crucially, why it is better than the dozens of other options that are out there in programming land?</comment>


The React Newsletter #27 - <AUTHOR> http://react-tutorial.net/ <comment><AUTHOR> Later today the 27th React Newsletter with all the latest news will be sent. Subscribe to get your copy here: [http://react-tutorial.net/](http://react- tutorial.net/) or see the archive at [http://us4.campaign- archive2.com/home/?u=29c888baee9c05ccb61...](http://us4.campaign- archive2.com/home/?u=29c888baee9c05ccb614e1e92&id=aaae828db8)</comment>