Skip to content

Use tail calls where applicable #5

Open
@VrIgHtEr

Description

@VrIgHtEr

Lua specifies tail calls as part of the language, which can be taken advantage of in the code presented.

However, having function A calling function, B right at the end, like the following is not enough.

function B() dosomething() end

function A()
    B()
end

This is because lua doesn't know how many items function B will return and has to clean the lua stack up in case function B returns anything, because A is not supposed to return anything itself. This means that the last thing function A does is clean up the lua stack after B returns, not calling function B itself. Because of this, the tail call optimization cannot be applied.

However in the following similar snippet:

function B() dosomething() end

function A()
    return B()
end

Here, since function A returns exactly the same thing as function B, the last thing function A does really is calling function B (because after B returns, the lua stack will contain exactly what A needs to immediately return). So in this case, the call to B will be tail-call optimized and no extra stack space is used.

An example of where this optimization can be used (because we don't really care what the relevant functions return) is in the step function within the pong function, for example:

step = function(...)
    local stat, ret = coroutine.resume(thread, ...)
    assert(stat, ret)
    if coroutine.status(thread) == 'dead' then
        return (callback or function() end)(ret)
    else
        assert(type(ret) == 'function', 'type error :: expected func')
        return ret(step)
    end
end

and in the callback inside the join function:

local callback = function(...)
    acc[i] = { ... }
    done = done + 1
    if done == len then
        return step(unpack(acc))
    end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions