Remix.run Logo
koito17 11 hours ago

As the other commenter pointed out, this isn't restricted to strongly-typed functional languages.

Clojure has core.async, which implements "goroutines" without any special support from the language. In fact, the `go` macro[1] is a compiler in disguise: transforming code into SSA form then constructing a state machine to deal with the "yield" points of async code. [2]

core.async runs on both Clojure and ClojureScript (i.e. both JVM and JavaScript). So in some sense, ClojureScript had something like Golang's concurrency well before ES6 was published.

[1] https://github.com/clojure/core.async/blob/master/src/main/c...

[2] https://github.com/clojure/core.async/blob/master/src/main/c...

Blackthorn 10 hours ago | parent [-]

> something like Golang's concurrency

That's wildly overselling it. Closure core async was completely incapable of doing the one extremely important innovation that made goroutines powerful: blocking.

koito17 7 hours ago | parent | next [-]

Assuming "blocking" refers to parking goroutines, then blocking is possible.

  (let [c (chan)]
    ;; creates channel that is parked forever
    (go
      (<! c)))
The Go translation is as follows.

  c := make(chan interface{})
  // creates goroutine that is parked forever
  go func() {
    <-c
  }()
Blackthorn 17 minutes ago | parent [-]

No, blocking refers to calling a function that blocks. Core.async can't handle that because macros are actually not capable of handling that, you need support from the runtime.

Call a function that blocks in go, the routine will park. Do that in Clojure and the whole thing stalls.

conjurernix 9 hours ago | parent | prev [-]

Can you elaborate? As far as I'm aware if you pull from an empty nchannel it wikl be blocking ubtik it gets a value.