Back in the early days of nodejs, we had an interface known as node
promises. They were basically event emitters that emitted "value" and
"error" events. This was terrible, so we removed them in favor of
callbacks. During this transition I proposed and pushed for a style
known as "continuable". I even wrote a howtonode article about it at
<
http://howtonode.org/do-it-fast>
Basically the change in luvit would be to change all functions that
accept a callback as the last arg to instead return a curried version
of the function that accepts the same callback.
Before:
-- simple async function with optional arg
local function doIt(arg1, arg2, callback)
if type(arg2) == "function" and type(callback) == "nil" then
callback = arg2
arg2 = "default value"
end
callback(nil, arg1 .. ":" .. arg2)
end
doIt("Hello", function (err, result)
p(err, result)
end)
After:
-- simple async function with optional arg
local function doIt(arg1, arg2) return function (callback)
if not arg2 then arg2 = "default value" end
callback(nil, arg1 .. ":" .. arg2)
end end
doIt("Hello")(function (err, result)
p(err, result)
end)
As you can see this adds a little boiler plate when defining an async
function, but it's not too bad. But it's way more powerful. It's a
cross between the raw callback and a promise or monad. Also handling
optional args is much since the callback is never misaligned.
The real power comes from the fact that you can use the returned
function from the first call and do things with it. Powerful flow
control libraries (like Do in the article) can be written. Also
something I realized yesterday is this makes working with coroutines
really nice!
createFiber(function (wait)
-- Auto suspend the thread and resume with the callback's results
local err, result = wait(doIt("Hello", "World"))
-- Same, but true flag means to auto-handle the err parameter
local result = wait(doIt("Hello"), true)
end)
Unlike the current fiber module that requires wrapping every function
before using in every coroutine that uses it, this requires no
wrapping at all. The wait function works on any of the returned
continuables from any new style async function.
Also I've been feeling out the syntax in various languages. It's
really pretty in coffeescript, and I imagine also in moonscript.
https://gist.github.com/1b47cba9f3a066147966
My question is how much of a burden would this be for everyone to port
their code to this format? Is it a deal breaker or an annoyance. Do
you like the idea or think it's stupid?
-Tim Caswell