闭包
- lua中的函数都可以认为是闭包,只不过为了便于理解还是用了函数的概念。
- lua中函数的返回值可以是匿名函数,也就是闭包。以下面的代码为例,提出一个概念:非局部的变量。在下面的代码中,匿名函数访问了一个变量i,它对于newCount来说是局部变量,对于匿名函数来说是既不是局部变量也不是全局变量,在lua中这个称谓非局部的变量。
- 在lua中一个闭包指的是一个函数和该函数所需要访问的非局部的变量。lua会把它们看做是一个整体,因此在下面的代码中多次允许c1和c2,会发现变量i是在递增的。这是因为
c1 = newCount()
这句代码相当于给c1赋值了一个闭包,它包含了i这个变量。因此多次执行相当于就是在反复执行一个对象,这样i就一直是原来那个i。
1 | function newCount() |
利用闭包的沙盒
- 下面这段代码中,修改了math库的sin方法。类似的还可以用来处理一些不安全的代码,这样的方式类似沙盒,将不安全包装了起来。
1 | print(math.sin(45)) |
直接使用非全局函数做递归会报错
- 当你尝试调用下面的代码时,会提示
attempt to call global 'foo' (a nil value)
,很奇怪对吧,明明定义的foo是个local的,怎么会提示是global呢?这个是因为在调用foo(x-1)时,这个foo函数还没有定义完,因此表达式在尝试调用一个全局的函数foo,但是显然这个全局函数是不存在的。
1 | local foo = function (x) |
- 正确的递归函数姿势,第二种
local function foo(x)
其实是第一个方法的语法糖。
1 | local foo |
正确的尾调用
- 本质是为了不记录函数的返回位置,这样在栈中就可以无限的调用函数。在lua中只有
return <func>(<args>)
这样的形式才是尾调用。