《programming in lua》里面举了一个非常生动的例子:
a = {p = print}
a.p("Hello World") --> Hello World
print = math.sin -- `print' now refers to the sine function
a.p(print(1)) --> 0.841470
sin = a.p -- `sin' now refers to the print function
sin(10, 20) --> 10 20
意味着当我们把函数变量指向另一个函数的时候,原地址依然保存着那份函数,可以用其他变量名指向这个函数,并接着调用。
table.sort实际上就是一个典型的高级函数,其第二个参数即是function类型的,用于确定两个值哪个值应当在前:
table.sort(list,function(a,b)
return a > b
end)
这是我认为lua最灵活强大的功能之一。
词法定界的意思即是,局部函数内部可以访问局部函数外部的变量:
bAscending = true
a = {2,3,1,6,7,8}
table.sort(a,function(num1,num2)
if bAscending then
return num1 < num2
else
return num1 > num2
end
end)
for i = 1,#a do
print(a[i])
end
如上,bAscending可以在比较函数外面被访问到。
官方文档中一个更有意思的示例代码,我修改了一点以更清晰:
function newCounter()
local i = 0
local f = function() -- anonymous function
i = i + 1
return i
end
print(f)
return f
end
c1 = newCounter() --> function: 000001A8D24EB820
print(c1()) --> 1
print(c1()) --> 2
c2 = newCounter() --> function: 000001A8D24EBAC0
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2
再略微修改上方的一些代码,观察输出:
function newCounter()
local i = 0
local f = function() -- anonymous function
i = i + 1
return i
end
print(f)
return f
end
c1 = newCounter -->
print(c1()) --> function: 000001D128558270 function: 000001D128558270
print(c1()) --> function: 000001D128558840 function: 000001D128558840
c2 = newCounter -->
print(c2()) --> function: 000001D1285583F0 function: 000001D1285583F0
print(c1()) --> function: 000001D128558600 function: 000001D128558600
print(c2()) --> function: 000001D1285582A0 function: 000001D1285582A0
发现不一样的地方了吗?
有几点我们需要额外注意:
很简单的一个概念,即return一个新函数时,不开辟额外栈空间去单独执行,而更类似于goto的状态转换。计算机基础里面有提到过,函数内部调用函数相当于开辟一个栈空间去执行,以此类推,直到一层层返回值即一层层清除栈空间,所以会有“调用函数会占空间”的这么一个说法。但是如下示例时:
function f(x)
return g(x)
end
lua解释器利用“调用g后不会再做任何事情,这种情况下当被调用函数g结束时程序不需要返回到调用者f”的特性,直接采用类似goto的做法跳转到g(x)执行,所以理论上尾调用递归的层次可以无限制的。但是需要分清什么是尾调用,只有return g(...)的情况才是,任何其他情况比如先g(...)再return,或者return g(...)+1这种都需要开辟额外栈空间。