Lua中在调用函数时使用多个括号

我正在学习Lua中的柯里化并看到了下面的代码:

function addup(x)
  local sum = 0
  local function f(n)
    if type(n) == "number" then
      sum = sum + n
      return f
    else
      return sum
    end
  end
  return f(x)
end

print(addup (1) (2) (3) ())  --> 6
print(addup (4) (5) (6) ())  --> 15

我假设 (1) (2) (3) () 部分表示按顺序而不是同时将值传递给函数。我的问题是我无法确切地弄清楚这些值如何通过函数传递以及函数如何操作它们。那么第一个值是赋值给x的,但第二个值会怎样?它会作为n传递到内部函数中吗?那么第三个值去哪里了?

我对另一行有问题:

return f

在这里,函数返回自身而没有任何值甚至是括号。我知道你可以将字符串或表格传递给一个函数,并省略括号,但这不是本案例。那么到底发生了什么?

我查看了手册,但没有发现关于这两个特性的任何内容。我真的很感谢您提供详细解释或链接到涵盖这些信息的手册。谢谢。

更新: 我参考的教程链接 - http://lua-users.org/wiki/CurriedLua

正如其中一个答案所指出的,Lua中不存在 (x)(y) 语法。它实际上是一系列函数调用。这在教程中并没有被提到,但是这是我的假设,结果证明是错误的,因此我已经将这一部分编辑了出去。

问题已解决。感谢您所有的答案,它们都非常有帮助。

点赞
用户7396148
用户7396148

addup 仅被调用了一次。返回的函数 f 是在每次调用 addup(1) 之后所调用的。

sumf 的一个上值(upvalue)。一旦 f 被定义,每次调用 f 都会更新相同的 sum 变量。这就是函数如何记住累计总数的方法。

下面是另一种编写第一个序列的方法:

local sumfunction = addup(1) --创建函数并且将其首次调用参数设为 1
sumfunction(2)               --使用参数 2 调用函数并且更新 sum
sumfunction(3)               --再次使用参数 3 调用函数并且更新 sum
print(sumfunction())         --没有参数调用函数,导致返回 sum

这样做可以完全去掉 f 的返回值,并只需要对 addup 进行一次调用就可以了。

返回值是必需的,以便像原始代码中那样链式调用 addup (1) (2) (3) ()。否则,语法就是无效的。

2020-06-22 18:11:22
用户7504558
用户7504558
局部变量 _L = {}
函数 addup(x)
  局部变量 sum = 0
  _L["f"] = function (n)
    如果类型为"number"的话
      sum = sum + n
      返回 _L["f"]
    否则
      返回 sum
    结束
  结束
  返回 _L["f"](x)
结束

打印(addup(1)(2)(3)())  --> 6
打印(addup(4)(5)(6)())  --> 15

"返回f" - 返回一个指向在局部命名空间中的函数的引用,它只是一个表。

2020-06-22 18:12:08
用户4984564
用户4984564

在这里,一个函数返回自身,没有任何值或者括号。我知道你可以将一个字符串或者表作为参数传递给一个函数,省略括号,但在这个例子中并不是这样。那么是怎么回事呢?

在Lua中,函数只是值。

你可以像这样调用它们:

print("Hello, World!")

但你也可以像这样将它们赋值给变量:

foo = print
foo("Hello, World!")

或将它们作为参数传递给其他函数并返回它们:

function call_twice(f)
   return function()
      f()
      f()
   end
end

call_twice(function()
   print("Hello, World!")
end)

事实上,

local function foo() return 42 end

只是另一种写法

local foo
foo = function() return 42 end
2020-06-23 10:51:07
用户2858170
用户2858170

Lua 中没有 (x)(y) 语法。这就是为什么您在手册中找不到任何内容。 (x)(y) 本身将导致语法错误。

addup (1) (2) (3) () 是一系列的函数调用。要理解这一点,必须仔细阅读 addup 的代码,并意识到函数调用只是一个函数值后跟调用运算符,而函数只是可以像其他任何类型一样返回的值。

该表达式从左到右进行求值。

调用运算符 () 对其左侧的值进行操作。因此,首先我们评估 addup(1),它调用全局函数 addup

addup 定义了本地数字值 local sum = 0 和本地函数值 f

local function f(n)
    if type(n) == "number" then
      sum = sum + n
      return f
    else
      return sum
    end
  end

然后返回用 addup 的参数 x 调用的该函数的返回值。

return f(x)

sumf 的上值,这是在定义 f 时在范围内的值。因此,每次调用 f 时,它都可以访问 sum

因此,n 在函数 f 中变为 x。由于 n 是数字值,f 将把 n 添加到 sum 中,并返回 f 自身。

因此,addup(1) 评估为对 f 的引用,一个具有上值 sum == 1 的函数值。

现在,我们已经在 (2) 左侧有了这个返回的函数值,这是另一个对 f 的函数调用。这次,n2。同样,它是一个数字,因此它将被添加到 sum 中,f 将再次返回自身。

现在,f(3) 调用。同上。

最后,使用 () 调用 f。这次,nnilf 返回 sum。 因此,addup (1) (2) (3) () 最终评估为在交给 print 之前为 6

不确定您从哪里获取该示例,但对我来说并不太合理。有更简单的方法来解释上值和闭包。这样的代码难以阅读和理解。

2020-06-23 13:55:34