Lua - 将带参数的函数调用添加到堆栈并稍后调用它们

时间:2017-05-01 12:47:14

标签: lua lua-table

我知道我可以在表格中存储函数引用,并使用这里的第一个答案中描述的参数调用它们

Lua - Execute a Function Stored in a Table

但我需要在每个调用的表中存储参数。我怎么能这样做?

解释我想做什么。我想写一个转向行为课。如果您正在计算转向力,您可以调用不同的功能,如搜索(目标)或追踪(目标)。

我希望能够“收集”所有函数调用并在结束时执行它们(循环遍历表并使用存储的参数执行每个函数)或取消所有函数。

这可能吗?

4 个答案:

答案 0 :(得分:2)

另一种(可能更清洁的)替代方案:

function verifyRequiredParams($required_fields) {
    $error = false;
    $error_fields = "";
    $request_params = array();
    $request_params = $_REQUEST;
    // Handling PUT request params
    if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
        $app = \Slim\Slim::getInstance();
        parse_str($app->request()->getBody(), $request_params);
    }
    foreach ($required_fields as $field) {
        if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
            $error = true;
            $error_fields .= $field . ', ';
        }
    }

    if ($error) {
        // Required field(s) are missing or empty
        // echo error json and stop the app
        $response = array();
        $app = \Slim\Slim::getInstance();
        $response["error"] = true;
        $response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
        echoRespnse(400, $response);
        $app->stop();
    }
}

答案 1 :(得分:2)

如果已知的最大可能参数数量很少,则可以使用闭包执行简单的操作。

local function bind(f, p1, p2, p3, p4, p5)
  return function()
    return f(p1, p2, p3, p4, p5)
  end
end

绑定后,值类型将是不可变的,并且所有参数都将被传递(甚至是nils)。

local hello = bind(print, 'hello', 123)
hello()  --> hello   123     nil     nil     nil

当然,您也可以绑定到引用类型。

local coords = { x=0, y=0 }

local t1 = bind(function(t, n) t.x = t.x + n end, coords, 20)
local t2 = bind(function(t, n) t.y = t.y + n end, coords, 50)

t1(); print('transform1', coords.x, coords.y)   --> 20   0
t2(); print('transform2', coords.x, coords.y)   --> 20   50
t1(); print('transform1', coords.x, coords.y)   --> 40   50

并且,您仍然可以将所有内容存储在表格中。

local t = {
  bind(function(a, b) return 'add', a + b end, 5, 5),
  bind(function(a, b) return 'sub', a - b end, 5, 5),
  bind(function(a, b) return 'mul', a * b end, 5, 5),
  bind(function(a, b) return 'div', a // b end, 5, 5),
}

for _, f in ipairs(t) do
  print(f())
end

--> add     10
--> sub     0
--> mul     25
--> div     1

答案 2 :(得分:0)

如果你想在一个表中存储一个函数和一些参数,然后用这些参数调用函数,那么,你只需将参数与函数一起存储在表中,然后将它们作为参数传递:

functions_with_parameters = {
  { 
    f = function (a, b) return a + b end, 
    args = { 1, 2 }
  },
  { 
    f = function (a, b) return a - b end, 
    args = { 100, 90 }
  }
}

for _, a in pairs(functions_with_parameters) do
  print(a.f(a.args[1], a.args[2]))
end
// 3
// 10

答案 3 :(得分:0)

这就是我要做的事情:

-- pack one func + args into a table
function record( f, ... )
    return { func = f, n = select( '#', ... ), ... }
end

-- take a list/array/sequence of `record`ed functions & run them
function run( list )
    for _, callinfo in ipairs( list ) do
        callinfo.func( table.unpack( callinfo, 1, callinfo.n ) )
    end
end

样品使用:

todo = { }
todo[#todo+1] = record( print, "foo", "blah", nil, 23 )
todo[#todo+1] = record( print, "baz" )
run( todo )
-->  foo    blah    nil 23
-->  baz

一些明显的变化包括在pcall中执行run(因此错误不会在中间中止),或者添加一个额外的函数( list, f, ... )以及哪些包通话信息&amp;将其附加到列表中。

如果您可以确定参数列表中间没有nil,则可以简化为......

-- pack one func + args into a table
function record( f, ... )
    return { func = f, ... }
end

-- take a list/array/sequence of `record`ed functions & run them
function run( list )
    for _, callinfo in ipairs( list ) do
        callinfo.func( table.unpack( callinfo ) )
    end
end

...但我强烈建议只在最后完成其余代码并且知道(测量!)这样做时才这样做是慢的。 (如果有一个错误将偶然的nil引入参数列表,这个版本将更改参数列表(通过删除元素),而第一个将通过它更改无论如何,这都是调试友好的。)

如果你真的缺乏空间,你可以通过不使用该功能的命名字段来节省一个值的空间......

附录:除了Lua 5.2之外,这似乎也比上面的其他两个版本快一点 - 请参阅下面的评论。)

-- (you can actually just do this inline)
function record( f, ... )  return { f, ... }  end

-- take a list/array/sequence of `record`ed functions & run them
function run( list )
    for _, callinfo in ipairs( list ) do
        callinfo[1]( table.unpack( callinfo, 2 ) )
    end
end

...但这取决于参数的数量,实际上可能会浪费空间! (对于x86_64上的vanilla(PUC-Rio)Lua,它为0,1,3或7个参数保存16个字节(1个TValue),对2个或6个参数不执行任何操作,4个用于浪费32个字节,5个用于16个字节8个参数的112个字节(并且相同的2次幂模式不断增长/重复)。)