lua-users home
lua-l archive

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


Hi list,

I'm studying coroutine's usage. it implemented with C's
setjmp/longjmp. In C, after we do a longjmp, we will return setjmp,
and can try again. to run a same routine. like this:

int a = 1;
setjmp(jbuf, 0);
if (a == 1) {
   a == 2;
   longjmp(jbuf);
}
assert(a == 2);

the if statement can eval twice. each setjmp has the ability to re-try
remain programs, this is the ability that implement a "amb"[1]
function.

the question is: how can I do this in Lua?

local f = amb_func(function()
    local a = amb(1,2,3,4,5)
    if a ~= 3 then amb() end
    print(a)
end)
f()

in amb_func, function will put into a coroutine. in the call
amb(1,2,3,4,5), amb will set a "longjmp point", and resume coroutine,
if we reach amb(), the coroutine can "re-try" from the resume point,
like  this:

local function amb(...)
    return coroutine.yield(...)
end

local function amb_try(cb, co, ...)
    local r = {coroutine.resume(co, ...)}
    if not table.remove(r, 1) then return end
    for _, v in ipairs(r) do
        local newco = coroutine.clone(co) -- HERE!
        local res, errmsg = pcall(amb_try, cb, newco, v)
        if res then
            cb(true, errmsg)
        elseif errmsg ~= 'no more tree' then
            cb(false, errmsg)
        end
    end
    error "no more tree"
end

local function amb_func(f)
    local co = coroutine.create(f)
    return coroutine.wrap(function(...)
        amb_try(coroutine.yield, co, ...)
    end)
end

but this idea need a way to "clone" a coroutine to prepare next retry.
is that a way to make coroutine retried from previous resume? or are
there any other way to implement this?

--
regards,
Xavier Wang.