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 ?
没关系,因为根据 explanation,func 变量的本地版本尚不清楚,因此它会尝试调用全局版本。但是当我删除 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 这个问题很好。为清楚起见,关于问题的几点说明:
函数是值,因此如果没有问题的上下文,"global function" 就如标题中那样本身就没有意义。
变量绑定是编译器将代码中的标识符映射到变量的过程。关于变量绑定的问题通常出现在递归函数中,但绑定规则更简单、更通用。它们与递归、函数 definitions 甚至本地与全局都没有任何关系。尽管如此,函数定义的语法糖 statements 可能会混淆问题。
例如:
local x = x + 1
表达式中的 x
不是正在创建的 x
。它是哪个变量取决于上面的任何代码。它可以是在语句块中声明的局部变量或作为函数参数。这样的声明可以在同一个块或函数定义中,也可以在 以上 的外部。全局只是后备。
显然,如果在上面的示例中没有使用 local
,相同的名称将绑定到相同的变量。
y = y + 1
两个y
名称是同一个变量,但是,如上,哪个变量是由其他代码决定的。
这个函数定义语句类似:
function f() end
如果局部 f
在范围内,那么它就是编译器将 "f" 绑定到的变量,否则 "f" 在全局环境中。
我是 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 ?
没关系,因为根据 explanation,func 变量的本地版本尚不清楚,因此它会尝试调用全局版本。但是当我删除 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 这个问题很好。为清楚起见,关于问题的几点说明:
函数是值,因此如果没有问题的上下文,"global function" 就如标题中那样本身就没有意义。
变量绑定是编译器将代码中的标识符映射到变量的过程。关于变量绑定的问题通常出现在递归函数中,但绑定规则更简单、更通用。它们与递归、函数 definitions 甚至本地与全局都没有任何关系。尽管如此,函数定义的语法糖 statements 可能会混淆问题。
例如:
local x = x + 1
表达式中的 x
不是正在创建的 x
。它是哪个变量取决于上面的任何代码。它可以是在语句块中声明的局部变量或作为函数参数。这样的声明可以在同一个块或函数定义中,也可以在 以上 的外部。全局只是后备。
显然,如果在上面的示例中没有使用 local
,相同的名称将绑定到相同的变量。
y = y + 1
两个y
名称是同一个变量,但是,如上,哪个变量是由其他代码决定的。
这个函数定义语句类似:
function f() end
如果局部 f
在范围内,那么它就是编译器将 "f" 绑定到的变量,否则 "f" 在全局环境中。