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 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...
随机推荐
- bzoj2351 2462
我没写hash,写了一些奇怪的做法,好像被hash随便操了…… 如果没有多测,那么这道题是白书上的例题 把询问矩阵当作a个模板串,建成一个ac自动机 把一开始的矩阵当作n个串放到自动机上匹配,找到a个 ...
- bzoj3672
感觉是noi2014中最有价值的一道题了 我们先考虑链上这个问题怎么做…… 如果没限制,那就是SB的斜率优化 我们可以得到这个式子(f[j]-f[k])/(s[j]-s[k])<p[i] 点横坐 ...
- 注解框架ButterKnife
将插件升级到1.3后支持Android Studio1.3 + ButterKnife7 如何使用 有所使用的布局 ID 上点击右键 (例如上图中的 R.layout.activity_setting ...
- 【 D3.js 高级系列 — 10.0 】 思维导图
思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩展来的,其中的树状图(tree layout)和集群图(cluster layou ...
- 【Unity3D】自动寻路(Nav Mesh Agent组件)
1.首先添加场景模型 2.为场景模型(寻路路径)添加NavMesh渲染,操作:Windows->Navigation->勾选Navigation Static选项->不勾选Gener ...
- iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数 iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, ...
- hihocoder 1228 Mission Impossible 6
题意:一个模拟……大概就是模拟一个编辑文档的过程……具体的还是读题吧…… 解法:刚开场就发现的一个模拟……果断敲起来…… 要注意几点与实际编辑过程不同: 1.当用C操作标记一段字符后,只有D会改变这段 ...
- Reading or Writing to Another Processes Memory in C# z
http://www.jarloo.com/reading-and-writing-to-memory/ Declarations [Flags] public enum ProcessAccessF ...
- bzoj3884: 上帝与集合的正确用法 欧拉降幂公式
欧拉降幂公式:http://blog.csdn.net/acdreamers/article/details/8236942 糖教题解处:http://blog.csdn.net/skywalkert ...
- Mobile testing基础之签名
1. 什么是数字签名? 数字签名就是为你的程序打上一种标记,来作为你自己的标识,当别人看到签名的时候会知道它是与你相关的 2. 为什么要数字签名? 最简单直接的回答: 系统要求的. Android系统 ...