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

esg*_*dir 3 variables recursion lua scripting-language

我对lua很新,我想了解以下行为.

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

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

print( func( 5 ) )
Run Code Online (Sandbox Code Playgroud)

程序将失败并出现错误:

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 ?
Run Code Online (Sandbox Code Playgroud)

这是好的,因为根据解释,func变量的本地版本尚不知道,所以它试图调用全局版本.但是当我删除本地关键字时,以下代码正常工作?

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

print( func( 5 ) )
Run Code Online (Sandbox Code Playgroud)

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

Vla*_*lad 7

引用全局func的第二个例子不是第一个例子吗?

它是 :)

你看,编译新函数时是否存在值无关紧要.它不检查存储在func变量中的值,而是每次调用时都会查找它.唯一重要的是变量的可见性.如果变量在本地范围内不可见,则它被视为全局变量,并将在全局环境表中查找.有关详细信息,请参阅Lua手册,第3.5- 可见性规则

第一个示例不起作用,因为local func在计算完整表达式之前变量不可见.这就是为什么第一个例子中断,试图调用缺少的全局变量.

如果您希望该func是本地的,请声明该变量,然后分配它.喜欢:

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

print( func( 5 ) )
Run Code Online (Sandbox Code Playgroud)

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

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

print( func( 5 ) )
Run Code Online (Sandbox Code Playgroud)

它将被精确翻译为相同的声明变量序列,然后分配它.

这次func变量对于new是可见的function(n),因此它将读取从该特定upvalue调用的值.

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