varags函数返回vargas lambdas lua

Jul*_*ian 4 lambda lua scope variadic-functions

如果我想编写一个接受varargs的函数并返回一个接受vargas的函数,我会遇到模糊不清...的问题

    function bind(func, ...) return function(...)  func(..., ...) end end
Run Code Online (Sandbox Code Playgroud)

Pig*_*let 5

首先,你错过了关闭绑定功能的结束.

如果您有歧义,只需使用不同的名称解决它们.

function bind(func, ...)
  return function(...)  func(..., ...) end
end
Run Code Online (Sandbox Code Playgroud)

如果我们测试你的代码: bind(print, "a", "b", "c")(1,2,3)

你会得到输出:

1 1 2 3

如果在函数参数列表中有...或任何其他名称,则该变量将是该函数范围内的本地变量.它优先于优越范围内具有相同名称的任何其他变量.所以...在你的匿名函数中与函数绑定无关.

要解决此问题,您可以简单地执行类似的操作

function bind(func, ...)
  local a = table.pack(...)
  return function(...)  func(table.unpack(a, 1, a.n), ...) end
end
Run Code Online (Sandbox Code Playgroud)

现在调用bind(print,"a","b","c")(1,2,3)将输出:

1 1 3 3

要了解b和c发生了什么,请阅读本节:https://www.lua.org/manual/5.3/manual.html#3.4.11

(当然还有Lua手册的其余部分)

调用函数时,参数列表将调整为参数列表的长度,除非该函数是vararg函数,该参数由参数列表末尾的三个点('...')表示.vararg函数不会调整其参数列表; 相反,它收集所有额外的参数并通过vararg表达式将它们提供给函数,该表达式也写为三个点.此表达式的值是所有实际额外参数的列表,类似于具有多个结果的函数.如果在另一个表达式内或表达式列表的中间使用vararg表达式,则将其返回列表调整为一个元素.如果表达式用作表达式列表的最后一个元素,则不进行任何调整(除非最后一个表达式括在括号中).

所以像func(...,...)这样的东西永远不会起作用,即使......是两个不同的列表.

为避免这种情况,您必须连接两个参数列表.

 function bind(func, ...)
  local args1 = table.pack(...)
  return function(...)
      local args2 = table.pack(...)

      for i = 1, args2.n do
          args1[args1.n+i] = args2[i]
      end
      args1.n = args1.n + args2.n

      func(table.unpack(args1, 1, args1.n))
  end
end
Run Code Online (Sandbox Code Playgroud)

bind(print,"a",nil,"c")(1,nil,3)

这最终给了我们想要的输出:

没有1无1

但我相信你可以想出一个更好的方法来实现你的目标,而不是连接各种varargs.