lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On Fri, May 11, 2012 at 3:03 AM, Tim Caswell <tim@creationix.com> wrote:
My only warning [...] Any function call into a third-party library will have the potential to suspend your current coroutine [...] callbacks makes the points where other stuff can happen explicit.

Coroutines make thread switches inconspicuous, which is a bad thing in many^H^H^H^Hsome situations (after years using them extensively, I'm still happily surprised about how rarely they've bitten me).

What coroutines bring you is that your code is organised in a more fluid way: if you want to perform A() as soon as B() has been completed, you want to write it as "A(); B()". Callbacks nested 4 or 5 levels deep are not maintainable, because they're not readable (and they can't even be indented sensibly).

The generic way to overload the instructions chaining operator ";" is the monad, but it's impractically hard to get right without a type system as powerful as Haskell's to assist you. If you want to make thread-switching operations stand out, you can simply make it mandatory to call them in a protected environment:

local f = async_socket.connect('example.com', 80)
wait_for(f :write "GET / HTTP/1.0\r\nConnection: close\r\n\r\n")
local page = wait_for(f:read "*a")
print(page :match "\r\n\r\n(.*)")
assert(not pcall(f.write, f, "whatever"), "I shouldn't be able to write out of a wait_for protection call")

Instead of:

local f = async_socket.connect('example.com, 80, function(f)
f :write("GET / HTTP/1.0\r\nConnection: close\r\n\r\n", function(n)
f :read("*a", function(page)
print(page :match "\r\n\r\n(.*)")
end)
end)
end)

Turning the latter into the former is really what Haskell's ">>=" operator is all about.

In development mode, of course, it's important that functions which *might* fail *always do* fail, even if no actual rescheduling occurs. Otherwise you get random bugs.That's something Haskell's type system does guarantee, but Lua cannot do so without an additional code-checking tool.

But let me repeat: in practice, I haven't found it necessary to make blocking calls explicit through wait_for()-like protections. Beginners might beg to differ, but hopefully beginners don't write concurrent spaghetti code.