8 pointsby Redoubts6 hours ago2 comments
  • diegoholiveiraan hour ago
    The post advocates for structured concurrency, but it compares a language primitive with a library abstraction. In Go, implementing the same basic nursery concept is straightforward with `golang.org/x/sync/errgroup`:

      g, ctx := errgroup.WithContext(ctx)
    
      g.Go(func() error {
        return task1(ctx)
      })
    
      g.Go(func() error {
        return task2(ctx)
      })
    
      return g.Wait()
    
    If you don't care about error propagation or cancellation at all, the standard library also provides `sync.WaitGroup`.

    The author also seems to argue that structured concurrency is always preferable, but I do not think that is true. There are valid use cases for unstructured concurrency, particularly for long-lived or independently managed tasks.

  • adrian_b3 hours ago
    > Annoyingly, though, there is no standard name for this category of control flow constructs.

    That is wrong.

    There is a standard name: FORK. In 1963-11, in "A Multiprocessor System Design", Melvin E. Conway introduced the terms FORK and JOIN. A few months earlier, he had introduced the term "coroutine".

    The UNIX operating system hijacked the term FORK, and later the POSIX threads API hijacked the term JOIN in "pthread_join".

    However, the original JOIN was something far more useful than the POSIX pthread_join. Also, while when modern programmers hear about "fork" they tend to think about UNIX, the original FORK was something more general and easier to use than the UNIX "fork". Variants of the original FORK exist in a large number of programming languages, including Occam, Ada, OpenMP, Go etc., using various keywords.

    The Go language "go" already existed in 1964, in the programming language IBM PL/I. In PL/I, the equivalent of Go language "func(...)" was "CALL func(...)", while the equivalent of Go language "go func(...)" was "CALL func(...)TASK".

    In programming, very few really new things appear. Most so-called "new" things are just fancy new names for ancient and forgotten things.

    I do not agree with most of the author's criticism about directly spawning threads. There are other good solutions for the problems mentioned by the author, like error handling and inquiries about the status of concurrent threads.

    Moreover, the author's analogy with GOTO is also flawed and shows a misunderstanding of the nature of GOTO.

    There exists a set of frequently-used program structures, like several variants of conditional/alternative/iterative structures, which should be used in programming in the vast majority of cases, and which are higher-level, i.e. using them is possible without knowing the details about how they are really implemented by the compiler with GOTOs.

    Nevertheless it has been demonstrated mathematically that no such set can be complete, i.e. there remain cases when using explicit GOTO instructions is the only way of implementing optimal programs. In such cases eliminating the GOTO instructions can be done only by making the program inefficient, i.e. by increasing the amount of memory needed and the amount of executed instructions.

    Because the name GOTO has been tainted, many languages have rebranded some variants of GOTO with other terms, like "throw exception", "tail call", "break labelled loop", "continue labelled loop" (single-level "break" and "continue" are not GOTOs, because they use implicit labels, but when they are used with labelled loops they become GOTOs).