1. 25
  1.  

  2. 10

    After using Erlang and Go I don’t know why people keep choosing Go. Channels flip everything upside down whereas messages and inboxes are a much more natural way to manage concurrency. Coupled with Erlang’s first class support for introspecting processes there isn’t even a competition between who wins.

    A few jobs back I was at a Go shop and to put it midly it was mostly a mess. One example that comes to mind was a library that had no provisions for stopping a goroutine because its channel protocol just didn’t have provisions for it. So if you used this library and you had some timeout constraints then whatever goroutine was launched would leak because you wouldn’t get the result in time and wouldn’t be able to tell it to stop. In Erlang this would not have been a problem because we could have asked the runtime to kill the runaway/broken process. If you’re wondering why the library wasn’t fixed it’s because that would have required changing all the call sites to pass in extra arguments to pass in the pieces for telling the goroutine to stop and it was just too much hassle to bother. In the end for that specific use case someone rolled a custom solution that bypassed the library (exactly as the Go designers intended I guess).

    Go is an almost adequate language built in the Unix tradition. There are better tools but we just keep going for the hacky and simplistic solutions.

    1. 3

      My intro to erlang was awful. The library I happened to be using would return [x,y] or (x,y) or [x, (y)] or what have you with no rhyme or reason. Of course there’s no compile errors because it’s all dynamic. And bonus fun, it doesn’t actually crash where you expect because various list or tuple patterns can unpack each other. So then you plow forward and only die later when it turns out that y was really [y].

      1. 4

        I think that’s a generic problem for all dynamically typed languages. Fortunately Erlang has dialyzer: http://erlang.org/doc/man/dialyzer.html.

        1. 3

          This is one of the few areas where you get a feel for it over time. “Modern” erlang uses type specifications (dialyzer link below) and has compile time checking, sadly the error messages are not at elm or rust standards, and its not full HM like OCaml etc, but it’s pretty useful. It sounds like the library you’re using is not very functional in design. I generally like to keep these are functional as possible, possibly with a sum type return if error handling in line is needed.

          That aside, erlang’s strong points are superb concurrency and robustness under load. If that’s what you need then it’s really good. If you need something else you should choose it. single binaries? inline assembler? use something else, and let erlang do the coordination or network stuff. Pragmatic.

        2. 2

          If you’re wondering why the library wasn’t fixed it’s because that would have required changing all the call sites to pass in extra arguments to pass in the pieces for telling the goroutine to stop and it was just too much hassle to bother. In the end for that specific use case someone rolled a custom solution that bypassed the library (exactly as the Go designers intended I guess).

          So, you’re implying that Go is a bad language because you worked at a place where seemingly nobody cared about proper software design? You argument works for every language, simply replace Go with for example Java.

          1. 3

            I’m implying Go is a simplistic language that paints programmers into corners and other languages don’t have the same issues because they don’t treat programmers like children. Surprisingly, Go is an instance where the usual social problems play second fiddle to its technical issues.

            Quote from the horse’s mouth

            The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.

            http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/From-Parallel-to-Concurrent

            1. 5

              The contempt he has for their own engineers is striking. Doesn’t Google hire the best or doesn’t it?

              1. 3

                Google is a machine for printing money. You tell me what good engineers would do at Google.

                But to answer your question directly I don’t think Google top brass cares about the skill of their engineers. I think Google now is mostly a resume signaling mechanism and my plan is to get hired and quit so I can claim to be ex-Google.

                For anyone at Google that is totally not my plan so you should refer me and I promise not to quit within the first week.

          2. 2

            Channels flip everything upside down whereas messages and inboxes are a much more natural way to manage concurrency.

            Please could you explain that a bit more? I have written a bit of Go but no Erlang. Until I read your comment, I thought both handled concurrency in a similar way, i.e. CSP-style message passing. What’s the difference? How do channels “flip everything upside down” compared to Erlang’s message passing? Thank you!

          3. 4

            Reminds me of X10. They made a language which is deadlock free by construction. At least if you don’t start using locks but the language provides other mechanisms.

            http://x10-lang.org/

            1. 4

              Sounds like all these arguments apply to any threading program. Go is not the same as Goto because you keep your thread of execution, despite adding another.

              1. 2

                Yes, they do apply to any threading program, which is the point—you’re applying the analogy too literally. Goto is a low-level mechanism that was (largely) replaced by a higher-level mechanism (structured programming) that did the same work in a much more understandable and reliable way. In SAT terms, goto is to structured programming as today’s thread APIs are to structured concurrency.

                1. 2

                  We did have C style concurrency with pthreads, that just sucks. The go statement gives us back our ability to thread without the boilerplate. Nurseries remove the ability to “just take care of it while I’m not looking” with more boilerplate.

                  1. 3

                    Are the if/then and for statements just more boilerplate too, then?

                    1. 0

                      Yes. If we could do with zero boilerplate we would. Look at Shell with its && and || making it fast to test assumptions without the boilerplate of an if.

                      1. 5

                        Any time I look at raw TLA+ I’m reminded of how much I appreciate abstractions above logical dis/conjunction

                    2. 2

                      The article literally lists pthreads as an example of the “go statement.”

                2. 3

                  Happy to see this get more attention - it looks very promising!

                  If you’re interested in this article, you may be interested in https://lobste.rs/s/omhxgb/structured_concurrency_cross_language (submitted at nearly the same time) and in sustrik’s earlier work on structured concurrency, where I first became aware of this.

                  1. 2

                    Check out Eiffel’s SCOOP, too. It’s been ported to Java in past by academics. It was designed to make writing and verifying concurrent programs about as easy as sequential. Cant recall if it achieved goal im genersl but high usability vs prior methods.

                  2. 1

                    It’s an interesting idea, for sure.

                    This even extends to goto itself. You’ll find a few languages that still have something they call goto, like C, C#, Golang, … but they’ve added heavy restrictions. At the very least, they won’t let you jump out of one function body and into another.

                    Well, Lisp’s TAGBODY/GO offers a structure goto which can jump out of one function body and into another:

                    (defun foo (&aux bar baz)
                      (tagbody
                       step1
                         (setq bar (lambda ()
                                     (print "ran bar")
                                     (go step3)))
                       step2
                         (setq baz (lambda ()
                                     (print "ran baz")
                                     (go end)))
                         (funcall bar)
                       step3
                         (funcall baz)
                       end))
                    

                    The key is that it has lexical scope & dynamic extent, which works out really well in practice: the anonymous function stored in bar can jump out of it and into the body of its parent foo, but it can’t jump into its sibling anonymous function stored in baz.

                    I’m getting a bit excited imagining various nursery-based flavours of an ASYNC special form …

                    1. 1

                      Was the anchor intentionally added to the URL?

                      1. 1

                        No but I can’t remove it now :(

                      2. 1

                        I don’t see how this accomplishes the promise of fixing with.

                        with getanursery() as nursery:
                            with open() as file:
                                nursery.start_soon(somefunction, file)
                            # file is gone. somefunction goes kaboom
                        
                        1. 0

                          nursery’s might be great. ok, go use them.

                          Go statement considered harmful? Give me a break. in that case… fork/exec is a goto, it’s harmful. pthread_create is a goto, it is harmful.

                          • no its not (harmful)
                          • no its not (a goto)
                          1. 5

                            Wow, I feel like people are really missing the point here. It’s an analogy—of course the go statement isn’t literally a goto. But it is a unidirectional transfer of control to code that can do absolutely anything, thus “unstructured” like a goto is. So yeah, pthread_create is harmful—have you ever debugged ad-hoc threaded code with no rhyme or reason (aka “structure”) to it?

                            Maybe it’s because I actually started programming back when structured programming was still a bit controversial, but this analogy seems intuitive to me.

                            And I’ve done enough Go programming now to recognize that it is indeed easy to write spaghetti concurrency with go statements, like it was easy to write spaghetti flow of control with goto.