5 ms·
> async operations require a library to work for some reason Rephrased: ocaml is so flexible that async can be implemented as a library with no special support
by gabcoh 2y ago
> async operations require a library to work for some reason
Rephrased: ocaml is so flexible that async can be implemented as a library with no special support from the language.
This is the beauty of ocaml (and strongly typed functional languages more broadly)
- eru 2y ago> This is the beauty of ocaml (and strongly typed functional languages more broadly) I don't think that's anything specific to strongly typed functional languages. In eg Rust even the standard library relies on third party crates. Though it is still somewhat amusing to me that loops in Haskell are delivered via a third party library, if you ever actually want them. See https://hackage.haskell.org/package/monad-loops-0.4.3/docs/Control-Monad-Loops.html https://hackage.haskell.org/package/monad-loops-0.4.3/docs/C... I do agree that it's good language design, if you can deliver what would be core functionality via a library. Whether you want to integrate that library into the standard library or not is an independent question of culture and convenience. (Eg Python does quite well with its batteries-included approach, but if they had better dependency management, using third party libraries wouldn't be so bad. It works well in eg Rust and Haskell.)
- koito17 2y agoAs 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/clojure/clojure/core/async.clj#L443 https://github.com/clojure/core.async/blob/master/src/main/c... [2] https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/ioc_macros.clj#L194 https://github.com/clojure/core.async/blob/master/src/main/c...
- Blackthorn 2y ago> 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.
- conjurernix 2y agoCan you elaborate? As far as I'm aware if you pull from an empty nchannel it wikl be blocking ubtik it gets a value.
- koito17 2y agoAssuming "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 2y agoNo, 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.
- koito17 2y agoAssuming "function that blocks" means "the carrier thread must wait for the function to return" and "the whole thing" means the carrier thread, then core.async doesn't really have this issue as long as e.g. a virtual thread executor is used. There is a caveat where Java code using `synchronized` will pin a carrier thread, but this has been addressed in recent versions of Java.[1] [1] https://openjdk.org/jeps/491 https://openjdk.org/jeps/491
- Blackthorn 2y ago