lua 中的全局和局部递归函数

Global and local recursive functions in lua

我是 lua 的新手,我想了解以下行为。

当我尝试运行以下递归函数时:

local func = function ( n )
  if n == 1 then return 1
  else return n * func( n - 1 )
  end
end

print( func( 5 ) )

程序将失败并出现错误:

lua: main.lua:16: attempt to call a nil value (global 'func')
stack traceback:
main.lua:16: in local 'func'
main.lua:38: in main chunk
[C]: in ?

没关系,因为根据 explanationfunc 变量的本地版本尚不清楚,因此它会尝试调用全局版本。但是当我删除 local 关键字时,以下代码是否正常工作?

func = function ( n )
  if n == 1 then return 1
  else return n * func( n - 1 )
  end
end

print( func( 5 ) )

程序打印 120 作为结果,但全局 func 之前从未初始化或使用过。这怎么可能也不会引发错误?第二个例子是不是像第一个例子那样引用了 global func

Isn't the second example referencing to global func as it does in the first one?

是:)

你看,在编译新函数的时候,value 是否存在并不重要。它不会检查存储在 func 变量中的值,而是会在每次调用时查找它。唯一重要的是变量的可见性。如果该变量在局部范围内不可见,那么它被认为是全局的,并且将在全局环境中查找 table。有关详细信息,请参阅 Lua 手册,第 3.5 – Visibility Rules

第一个示例不起作用,因为 local func 变量在计算完整表达式之前是不可见的。这就是第一个示例失败的原因,它试图调用丢失的全局变量。

如果您希望该函数是局部的,请声明该变量,然后然后 分配它。喜欢:

local func
func = function ( n )
  if n == 1 then return 1
  else return n * func( n - 1 )
  end
end

print( func( 5 ) )

对于这种情况,使用 Lua 的语法糖可能会更容易:

local function func( n )
  if n == 1 then return 1
  else return n * func( n - 1 )
  end
end

print( func( 5 ) )

它会被翻译成完全相同的声明变量顺序,然后赋值。

这次 func 变量将对新的 function(n) 可见,因此它将读取值以从特定的上值调用。

请注意,稍后仍然可以通过将不同的内容分配给 func 变量来 "break" 函数。 Lua 中的函数(与任何其他值一样)没有名称,只有变量有。因此对函数的调用不是硬编译的,要调用的函数值总是在每次调用之前从变量中获取。

@Vlad answers 这个问题很好。为清楚起见,关于问题的几点说明:

  1. 函数是值,因此如果没有问题的上下文,"global function" 就如标题中那样本身就没有意义。

  2. 变量绑定是编译器将代码中的标识符映射到变量的过程。关于变量绑定的问题通常出现在递归函数中,但绑定规则更简单、更通用。它们与递归、函数 definitions 甚至本地与全局都没有任何关系。尽管如此,函数定义的语法糖 statements 可能会混淆问题。

例如:

local x = x + 1 
表达式中的

x 不是正在创建的 x。它是哪个变量取决于上面的任何代码。它可以是在语句块中声明的局部变量或作为函数参数。这样的声明可以在同一个块或函数定义中,也可以在 以上 的外部。全局只是后备。

显然,如果在上面的示例中没有使用 local,相同的名称将绑定到相同的变量。

 y = y + 1

两个y名称是同一个变量,但是,如上,哪个变量是由其他代码决定的。

这个函数定义语句类似:

 function f() end

如果局部 f 在范围内,那么它就是编译器将 "f" 绑定到的变量,否则 "f" 在全局环境中。