3

Given a vararg ... like 1, 2, 3, nil, 5, I would like to write a function reverse, such that reverse(...) returns the vararg 5, nil, 3, 2, 1.

2 Answers 2

2

Using a temporary table:

local function reverse(...)
    local n = select("#", ...)
    local t = {...}
    -- Reverse the table
    for i = 1, n/2 do
        local j = n - i + 1
        t[i], t[j] = t[j], t[i]
    end
    return unpack(t, 1, n)
end

or using a helper function which picks the n-th element, prepends that to a new vararg, and recurses until n = 0:

local function h(n, ...)
    if n == 0 then return end
    return select(n, ...), h(n - 1, ...)
end
local function reverse(...)
    return h(select("#", ...), ...)
end
Sign up to request clarification or add additional context in comments.

Comments

2

If you are interested in dropping down a level, the Lua C API provides lua_insert and lua_rotate (5.3+), both of which can be used to manipulate the stack directly.

An example using the former:

#include <lua.h>

static int reverse(lua_State *L)
{
    int n = lua_gettop(L);
    for (int i = 1; i < n; i++)
        lua_insert(L, i);
    return n;
}

int luaopen_reverse(lua_State *L)
{
    lua_pushcfunction(L, reverse);
    return 1;
}
local reverse = require 'reverse'

print(reverse(1, 2, 3, 4))
4   3   2   1

(The following focuses on the Lua 5.4 API, but should be applicable to Lua 5.3 as well. Note that in Lua 5.3+, lua_insert is a macro around lua_rotate.)

Interestingly, there is an internal API function called reverse, used by lua_rotate, which performs this task very efficiently across a stack segment.

If one has the ability to change the source code for their installation, then it is possible to modify src/lapi.c with the following function,

/* reverse the entire stack segment */
LUA_API void lua_reverse (lua_State *L)
{
    lua_lock(L);
    int n = lua_gettop(L);
    if (n > 1)
        reverse(L, index2stack(L, 1), index2stack(L, n));
    lua_unlock(L);
}

src/lua.h with the following protoype,

LUA_API void  (lua_reverse) (lua_State *L);

src/lbaselib.c with the following function,

static int luaB_reverse (lua_State *L) {
    lua_reverse(L);
    return lua_gettop(L);
}

and add

{"reverse", luaB_reverse},

to the base_funcs array in src/lbaselib.c, to get access to an efficient, global reverse function:

Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> reverse('hello', 'world', 42)
42  world   hello

(and a lua_reverse C API function, of course.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.