lua语言中的函数概念
来源:互联网 发布:linux驱动模块编译 编辑:程序博客网 时间:2024/06/05 02:46
1. 不同于C,lua中的函数是一种first-class-value,这意味着:
lua中的函数可以视作一种"值"存储到变量或table中;
可以作为其他函数的实参;
可以作为其他函数中的返回值;
可以嵌套在其他函数中被构造创建,而无需在设计阶段就定义好.
2. lua中的函数本身其实都是没有名字的,也就是说通常讨论的函数名(比如print),实际不过是持有某个函数的变量.
所以,lua中函数的标准定义形式其实是:
var = function (x) <body> end
也就是说,一个函数定义其实就是一条赋值语句,这条语句首先是构造一种类型为"函数"的值,然后将这个值赋给一个变量
3. 跟其他大部分语言一样,lua遵循"词法域"(即静态作用域)的原则,又因为lua函数是一种first-class-value,所以才有了闭包(closure)的概念:
一个闭包就是一个函数加上构造该函数时所需的所有"非局部的变量"(non-local variable)
一个闭包的典型例子如下:
function newCounter ()
local i = 0
return function () -- 匿名函数,也就是闭包
i = i + 1
return i
end
end
c1 = newCounter()
c2 = newCounter()
print(c1) -- 1
print(c1) -- 2
print(c2) -- 1
这个例子中,变量i对于匿名函数来说,既不是全局变量,也不是局部变量,所以就被称为了"非局部的变量";
调用函数newCounter的过程,其实就是创建一个闭包的过程;
这里要注意一点,函数名不带括号赋值给一个变量,其实是表示共同持有某个函数,而函数名带括号赋值给一个变量,其实是表示首先调用该函数,然后将该函数的返回值赋值给变量;
所以以上例子中,c1和c2是同一个函数所创建的两个独立的闭包,也就是说,它们各自拥有独立的i
4. lua函数中存在一种"尾调用"概念:
当一个函数的最后一个动作是调用另外一个函数,并且包含了关键字"return",那么这条调用就是该函数的尾调用。
利用这种"尾调用"现象,lua实现了"尾调用消除"机制,原理就是:
调用函数时,会在内存中形成一个"调用记录",主要保存调用位置和内部变量信息,经过多次嵌套调用函数之后,内
存中就会堆叠这些"调用记录",形成一个"调用栈"。由于"尾调用"是所在函数的最后一步操作,一旦开始执行"尾调
用"的函数,外层函数的调用记录就不会再用到,所以就直接释放这个调用记录,然后再写入"尾调用"的函数的调用
记录即可。
这种"尾调用消除"机制的意义很明显,那就是如果所有嵌套的函数都符合"尾调用",那么真个嵌套调用的过程中,调用记录同时只会有一项,这就大大节省了内存空间。
一个典型的应用例子就是"尾递归",调用以下函数时,传入任何数字都不会造成栈溢出:
function foo (n)
if n > 0 then
return foo (n - 1)
end
end
递归非常耗费内存,因为每次执行递归函数,就要往内存中增加一条调用记录,所以很容易发生"栈溢出"错误。但对于"尾递归"来说,由于同一时刻只会存在一个调用记录,所以永远不
会发生"栈溢出"问题。
- lua语言中的函数概念
- Lua中的环境概念
- Lua中的栈概念
- Lua中的环境概念
- Lua中的元表概念
- Lua中的面向对象概念
- Lua语言中的table
- lua中的时间函数
- Lua中的API函数
- lua中的函数
- lua中的递归函数
- lua中的时间函数
- lua中的require函数
- lua中的函数
- lua中的全局函数
- Lua中的unpack( )函数
- 四、Lua中的函数
- lua中的函数
- 我的vim配置文件
- webmagic 0.70学习
- Linux系统下解压缩*.tar.xz方法
- TCP的超时与重传
- Android多线程和异步消息的简单应用
- lua语言中的函数概念
- c语言数据结构
- Detours express3.0在VS2013中编译生产库
- Vue.js 学习3 模板
- 解决Python小问题:CRC check failed
- 编写一个方法,返回100个互不重复,且顺序被打乱的集合
- Java常用帮助类(1)验证帮助类
- SSM项目整合
- Java类加载