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 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...
随机推荐
- bzoj1499: [NOI2005]瑰丽华尔兹
dp. 首先我们可以看到每个时间段只能往一个方向转移最多t步(t为时间段的长度),所以我们可以按时间段dp.因为这个前后值互不影响,也不用占用这一维空间就可以省去. 然后每个时间段内是一列一列(行) ...
- VS2010解决方案不显示无法添加项目问题
问题:在VS2010中不显示解决方案,导致不能添加项目. 方法:工具-选项-项目和解决方案-选中“总是显示解决方案”,ok
- powerScript脚本
一.powerScript的语法 1.0变量的命名及使用 powerscript的标识符(变量名称)必须以字母或下划线开头,其它的字符可以是下划线(_).短横线(-).美元符号($).号码符号(#) ...
- 【MySQL】通过select语句把一列数据拼接成一条字符串
通过 GROUP_CONCAT(如下图)
- (function(){})()这个是什么?有不明觉厉的感觉么?
今天在RunJs上看到一个人分享的一个jquery代码,写的是jquery弹性滑动效果.不过,看着看着,发现一句代码(function{})(),突然有种不明觉厉的感觉. 事实上,只是因为我们没有用过 ...
- MySQL基础之第5章 操作数据库
假设已经登录 mysql-h localhost -uroot -proot 5.1.显示.创建.删除数据库 show databases; 显示所有的数据库 create database ...
- 【转】一致性hash算法(consistent hashing)
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- 【剑指offer 面试题13】在 O(1) 时间删除链表结点
#include <iostream> using namespace std; //构造链表结点 struct ListNode { int val; ListNode *next; L ...
- Face++接口封装
本节使用doCurlGetRequest函数来封装Face++的接口请求.我们在class文件夹下的faceStub.php文件中实现 一个faceStub类,封装请求Face++的相关接口. 实现代 ...
- Android-day02_广播
1.什么是广播 貌似一个人大声喊一句话,别人听到了这就是广播 2.在android中广播有标准广播和有序广播 标准广播也就是发送一个广播,所有人都能同一时间接收到 有序广播则是有顺序的广播,发送的时候 ...