Lua 学习笔记-闭包

闭包

1.什么是词法定界和闭包

当一个函数嵌套另一个函数定义时,内部函数可以访问外部的函数的局部变量,我们称之为词法定界 ,我们称这样的外部的局部变量(external local variable)或者 upvalue。

function newCounter()
	local i = 0;
	return function()
			i = i + 1;
		end
end

c1 = newCounter()
c2 = newCounter()
print(c1()) --->  1
print(c1()) --->  2
print(c2()) --->  1

匿名函数 使用 upvalue i 保存了他的计数,当我们调用匿名函数的时候i已经超出了作用的返回,因为创建i的newCounter 已经返回了。然而Lua用闭包的思想正确处理了这种情况。简单的说闭包是一个函数加上它可以正确访问的Upvalues。

2.非全局函数

Lua中函数可以作为全局变量也可以作为局部变量,
作为全局变量的申明方式有3种:

lib = {}
lib.func1 = function(x,y) return x + y end
lib.func2 = function(x,y) return x - y end
Lib = {
		func1 = function(x,y) return x + y end
		func2 = function(x,y) return x - y end
}
Lib = {}
functioin Lib.func1 (x,y)
		return x + y
	end
functioin Lib.func2 (x,y)
		return x + y
	end

当我们用局部变量保存函数时,我们就得到一个局部函数,也就是说局部函数就像局部变量一样在一定的范围内有效。局部函数的申明方式有2种:

local f = function (x, y) return x + y end
local g = function (x, y) return f(x , y) end
local function f(...)
	...
end

注意一点:在申明局部递归函数的时候 一定要先申明,否则会报错

local f = function(n)
	if n < 0 then
	 	return 1
	end
	return n*f(n-1)  --------------buggy	

上面的这段代码会有报错是因为Lua编译时遇到f(n-1)时它并不知道这个f是局部函数,Lua就回去查找是否有这样的全局函数f,为了解决这个问题 我们必须在定义之前申明这个函数:

local f
f = function(n)
	if n < 0 then
	 	return 1
	end
	return n*f(n-1)  --------------buggy	

3.正确的尾调用

尾调用是一种类似在函数结尾的goto调用,当函数最后一个动作是调用另外一个函数时,我们称之为尾调用

function f(x)
	return g(x)
end

f调用g后不会再做任何事情,这种情况下当被调用函数g结束时程序不需要返回到调用者f;所以尾调用之后程序不会在栈中保留关于调用者的任何信息。一些编译器比如Lua编译器在利用这种特性处理尾调用时不使用额外的栈,我们称这种语言支持正确的尾调用。
由于尾调用不需要使用栈空间,所以尾调用的递归层次也是可以无限制的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值