1
votes

Every time a function in Lua is called, the number of return values is immediately known at the call site:

f() --0
local a, b = f() --2
local t = {f()} --LUA_MULTRET
local t = {f(), nil} --1

The same is true for the C API: both lua_call and lua_pcall are always provided with the expected number of return values (or LUA_MULTRET).

Thinking about performance, it might be advantageous for a Lua function to be able to determine the number of expected return values expressed by their callers, so as to avoid computing return values that the caller did not request (if the computation takes a long time):

int getstrings(lua_State *L)
{
    if(lua_numresults(L) > 0)
    {
        lua_pushstring(L, "a");
        if(lua_numresults(L) > 1)
        {
            lua_pushstring(L, "b");
            if(lua_numresults(L) > 2)
            {
                lua_pushstring(L, "c");
                return 3
            }
            return 2;
        }
        return 1
    }
    return 0;
}

Assuming a hypothetical lua_numresults returns size_t, this function would produce only the that are really needed and will not take time to compute values that are guaranteed to be lost.

Another interesting example would be functions that return sequences:

int range(lua_State *L)
{
    size_t num = lua_numresults(L);
    for(size_t i = 1; i <= num; i++)
    {
        lua_pushinteger(L, i);
    }
    return num;
}

The sequence is not "lazy" so something like f(range()) cannot be done, but local a, b, c = range() returning 1, 2, 3 etc. might find its uses.

Is there anything like lua_numresults or a way to implement its functionality?

1

1 Answers

2
votes

Judging from Lua 5.3 sources, the expected number of results is located in the CallInfo structure. A new call info is created for every Lua call, and the most recent one is stored in lua_State::ci There doesn't appear to be any function that can return this value, but if one has access to the structure, it is fairly straightforward to get it:

#include "lua/lstate.h"

size_t lua_numresults(lua_State *L)
{
    return (size_t)L->ci->nresults;
}