Hacker News new | ask | show | jobs
by donjigweed 4518 days ago
"because it uses macros, the suspendable constructs are limited to the scope of a single code block, i.e. a function running in a suspendable block cannot call another blocking function; all blocking must be performed at the topmost function. It’s because of the second limitation that these constructs aren’t true lightweight threads, as threads must be able to block at a any call-stack depth"

Can you elaborate on this a bit? Let's say I have a function called 'fetch-url' which takes a core.async channel as an argument and makes a non-blocking http request (say, using http-kit), and in the callback handler i put the result onto the channel. If I'm in some other function, in which whose body I open a core.async go block and call fetch-url from within that go block, everything is still asynchronous is it not?

1 comments

If you're using callbacks at all, then you're not blocking. The main advantage threads (and lightweight threads) have is that they can block.

What you can't do is this:

  (defn foo [ch]
     (go 
       (bar ch)))

  (defn bar [ch]
     (<! ch))
foo starts a go block which calls bar, which then blocks on the channel. For threads that's ok:

  (defn foo [ch]
     (thread ; not sure about syntax here
       (bar ch)))

  (defn bar [ch]
     (<!! ch))
So a function running in a thread can call another function that blocks. A go block can't, that's why go blocks aren't lightweight threads.

BTW, in Pulsar's implementation of core.async, the first example is ok, too.