Lua学习笔记(三):函数和闭包
函数
lua的函数以function关键字开始,后跟函数名称和参数,最后以end结束,我们看一个简单的函数定义:
function foo()
--do something
end function add(a, b)
return a + b
end
在载入脚本时,函数不会执行,仅仅是会被载入内存和名称关联起来。
另外需要注意的是,调用的函数必须是在代码上方进行了定义的函数,否则运行时会报错,如下:
print(add(, ))--运行时这里会报错, 因为 add 还没有被载入到内存 function add(a, b)
return a + b
end print(add(, ))--正常调用
参数
在调用函数时,也需要将对应的参数放在一对圆括号中,即使调用函数时没有参数,也必须写出一对空括号。对于这个规则只有一种特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字符串或table构造式,那么圆括号便可以省略掉:
print "hello1"
print("hello2") function foo(a)
print(a)
end foo {, , , }
foo({, , })
函数的参数可以看做该函数体内的一个局部变量,调用函数时提供的实参数量可以与形参数量不同。Lua会自动调整实参的数量,以匹配参数表的要求,若“实参多余形参,则舍弃多余的实参;若实参不足,则多余的形参初始化为nil”:
function foo(a, b, c)
print(a, b, c)
end foo(, , , )--100 200 300
foo(, )--100 200 nil
foo()--nil nil nil
变长参数
使用“...”来定义参数,Lua会在函数中定义一个名为arg的table对象来保存传递的所有参数,如下:
function foo(...)
--arg.n 可以取得参数的长度
print("params length: ", arg.n)
--打印出所有的参数及其类型
for i = , arg.n do
print("param index: ", i, ", param value: ", arg[i], ", param type: ", type(arg[i]))
end
end foo()
foo(, , )
foo("abc", 3.14, true, {, , })
返回值
使用return可以返回值:
function add(a, b)
return a + b
end num = add(, )
print(num)--
Lua还支持返回多个值,返回值多余接收值,则舍弃多余的返回值;若返回值不足,则多余的接收值初始化为nil,和参数调用情况一直:
function foo(a, b)
return a + b, a * b, a - b
end num1, num2, num3 = foo(, )
print(num1, num2, num3)--300 20000 -100 num1, num2, num3, num4 = foo(, )
print(num1, num2, num3, num4)--300 20000 -100 nil num1, num2 = foo(, )
print(num1, num2)--300 20000 num1 = foo(, )
print(num1)--
深入了解Lua的函数
在Lua中,函数与其它传统类型的值具有相同的权利。函数可以存储到变量或table中,也可以作为实参传递给其它函数,还可以作为其它函数的返回值。在Lua中有一个容易混淆的概念是,函数与所有其它值一样都是匿名的,即它们都没有名称。当讨论一个函数名时,实际上是在讨论一个持有某函数的变量,比如下面的两个函数声明方式虽然不一样但实际上在Lua看来都是一致的:
function foo1()
--do sometging
end foo2 = function()
--do sometging
end
局部函数
实际上,一个函数定义实际就是一条语句(更准确地说是一条赋值语句),这条语句创建了一种类型为“函数”的值,并将这个值赋予一个变量。由于函数在Lua中就是一个普通的值,所以不仅可以将其存储在全局变量中,还可以存储在局部变量甚至table的字段中:
obj = {}
obj.add = function(a, b)
return a + b
end
obj.subtract = function(a, b)
return a - b
end print(obj.add(,))
print(obj.subtract(,))
再看一个例子:
do
local function add(a, b)
return a + b
end
local function subtract(a, b)
return a - b
end print(add(,))
print(subtract(,))
end print(add(,))--超出作用域, 报错
print(subtract(,))--超出作用域, 报错
闭包
闭包是由函数和与其相关的引用环境组合而成的实体。我们可以简单的理解为:子函数可以使用父函数中的局部变量,这种行为就叫做闭包。下面我们看一个经典的闭包例子:
function closure()
local i = --注意 i 被返回的函数使用
return function()
i = i +
return i
end
end c1 = closure()--函数作用域已经结束, 但是由于闭包的原因, i 仍然被保留了下来
print(c1())--
print(c1())--
print(c1())-- c2 = closure()--每次调用会产生闭包的方法, 都类似类一样会生成一个新的闭包函数, i 会重新计数
print(c2())--
print(c2())-- print(c1())-- c1 = nil--闭包保留的变量 i 会被真正销毁
更多Lua闭包的内容可以参考下面这篇博文:http://cn.cocos2d-x.org/tutorial/show?id=1078
Lua学习笔记(三):函数和闭包的更多相关文章
- swift学习笔记2——函数、闭包
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- Lua学习笔记3. 函数可变参数和运算符、转义字符串、数组
1. Lua函数可以接受变长数目的参数,和C语言类似,在函数的参数列表中使用(...)表示函数可以接受变长参数 lua函数将参数存放在一个table中,例如arg,那么#arg可以获得参数的个数 fu ...
- LUA学习笔记三·时间等操作系统库
1.构造时间 2.时间制定格式输出 3.计时器(闭包)os.difftime (t2, t1) 返回以秒计算的时刻 t1 到 t2 的差值. (这里的时刻是由 os.time 返回的值). 在 POS ...
- python学习笔记三 函数(基础篇)
函数 内置函数 常用的内建函数: type() 列出指定对象的类型 help() 能够提供详细的帮助信息 dir() 将对象的所有特性列出 vars() 列出当前模块的所有变量 file, ...
- Typescript 学习笔记三:函数
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- ES6学习笔记<三> 生成器函数与yield
为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...
- MYSQL学习笔记三:日期和时间函数
MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...
- [转]LUA 学习笔记
Lua 学习笔记 入门级 一.环境配置 方式一: 1.资源下载http://www.lua.org/download.html 2.用src中的源码创建了一个工程,注释调luac.c中main函数,生 ...
- Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...
- Matlab学习笔记 figure函数
Matlab学习笔记 figure函数 matlab中的 figure 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...
随机推荐
- FileZilla无法确定拖放操作的目标,由于shell未正确安装
天有不测风云,突然间,用filezilla下载ftp上的文件到桌面的时候,提示"无法确定拖放操作目标.由于shell未正确安装" 解决办法很简单,执行如下几步就OK了 1.在CMD ...
- [转] 搜索之双向BFS
转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...
- HDU 3746 Cyclic Nacklace 环形项链(KMP,循环节)
题意: 给一个字符串,问:要补多少个字符才能让其出现循环?出现循环是指循环节与字符串长度不相等.比如abc要补多个变成abcabc.若已经循环,输出0. 思路: 根据最小循环节的公式,当len%(le ...
- Java [Leetcode 190]Reverse Bits
题目描述: everse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represente ...
- 《C++ Primer 4th》读书笔记 第3章-标准库类型
原创文章,转载请注明出处:http://www.cnblogs.com/DayByDay/p/3911534.html
- <六>面向对象分析之UML核心元素之业务实体
一:基本概念
- 【转】使用 Auto Layout 的典型痛点和技巧
layoutIfNeeded()强制立刻更新布局 原文网址:http://www.jianshu.com/p/0f031606e5f2 官方文档:Auto Layout Guide 加上去年WWDC上 ...
- Iwpriv工作流程及常用命令使用
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数 iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, ...
- 《C++ primer》--第12章
习题12.7 什么是封装?为什么封装是有用的? 解答: 封装是一种将低层次的元素组合起来形成新的.高层次实体的技术.例如,函数是封装的一种形式:函数所执行的细节行为被封装在函数本身这个更大的实体中:类 ...
- DIV+CSS常见问题:DIV如何设置一个像素高度?
CSS如何控制DIV实现1像素高度呢?问题看起来很简单,但万恶的IE6会让你很麻烦,不过解决办法很多,本文将介绍最简单的一种:DIV{height:1px;line-height:1px;font-s ...