Lua学习(4)——函数
在Lua中函数的调用方式和C语言基本相同,如:print("Hello World")和a = add(x, y)。唯一的差别是,如果函数只有一个参数,并且该参数的类型为字符串常量或table的构造器,那么圆括号可以省略,如print "Hello World"和f {x = 20, y = 20}。
Lua为面对对象式的调用也提供了一种特殊的语法--冒号操作符。表达式o.foo(o,x)的另一种写法是o:foo(x)。冒号操作符使调用o.foo时将o隐含的作为函数的第一个参数。
Lua中函数的声明方式如下:
function add(a)
local sum = 0
for i, v in ipairs(a) do
sum = sum + v
end
return sum
end
1. 多重返回值(multiple results)
Lua允许函数多个结果
例如
s,e = string.find("hello lua world","lua")
function fun()
a="world"
b="hello"
return a,b
end i,j=fun()
print(i,j)
如果函数没有返回值或者没有足够多的返回值,那么Lua用nil来填充
x,y,z=fun()
z的值是nil
如果一个函数调用不是一系列的表达式的最后一个元素,那么将只产生一个值:
x,y=fun(),
-- x="hello" y=20
--fun() 返回 2个值"hello" "world"
强制返回一个元素加括号(fun())
> function fun() a="hello" b="world" return a,b end
> print((fun()))
hello
最后一个需要介绍的是Lua中unpack函数,该函数将接收数组作为参数,并从下标1开始返回该数组的所有元素。如:
> print(unpack{10,20,30})
10 20 30
unpack函数一个重要用途体现在泛型调用机制中。泛型调用机制可以动态以任何实参来调用函数。
关于unpack的使用请查看 http://www.cnblogs.com/corolla/p/3811793.html
function fun(a,b)
if a>b then
print(a)
else
print(b)
end
end
tb={,}
fun(unpack(tb))
当tb表的数量过多时
tb={,,}
fun(unpack(tb))
2. 变长参数
Lua中的函数可以接受不同数量的实参,查看以下例子:
function add(...)
local s =
for i,v in ipairs(...) do
s = s+v
-- print(v)
end
return s
end
tb={,,,}
print(add(tb))
local a,b = ...类似于一个具有多重返回值的函数
> function fun(...) local a,b=... print(a,b) end
> fun(,)
访问变长...参数,使用select函数,访问{...}和访问table一样。select{"#",...}取参数总数,local arg = select{i,...}访问第i个。遍历的例子如下
function fun(...)
local s=
n = select("#",...)
for i=, n do
local arg=select(i,...)
s = s+arg
end
return s
end tb={,,,}
print(fun(unpack(tb)))
3. 具名实参:
Lua中的参数传递机制是具有“位置性”的,也就是调用函数时,实参和形参必须一一对应。Lua并不直接支持这种语法,但可以通过一种细微的改变来获取相同的效果。主要是将所有实参组织到一个table中,并将这个table作为唯一的实参传给函数。
tb={old="temp.lua",new="new.lua"}
function rename(arg)
return os.rename(arg.old,arg.new)
end
rename(tb)
如果一个函数有大量的参数,其中大部分是可选的时候,具名参数传递的方法非常有用。
深入理解函数
Lua中函数是一种“第一类值”,它们具有的特定的词法域(Lexical Scoping)
“第一类值”表示Lua函数与其他的传统的值具有相同的权利。函数可以存储到变量中或table中。也可以作为实参传递给其他函数,也可以作为其他函数的返回值。
“词法域”是值一个函数可以潜逃在另一函数中,内部的函数可以访问外部函数中的变量。
在Lua中有一个容易混淆的概念是,函数与所有其他值一样都是匿名的,即他们都没有名称。函数名实际上是某函数的变量,与其他变量持有各种值是一个道理。
> tb={p=print}
> tb.p("hello world")
hello world
> print = math.sin --print==sin函数
> tb.p(print())
0.8414709848079
4. 闭合函数(closure)
若将一个函数写在另一个函数之内,那么这个位于内部的函数便可以访问外部函数中的局部变量
newCounter = function(add)
local i = ;
counter = function()
i = i + add
return i
end
return counter
end
c1 = newCounter()
print(c1()) print(c1())
- lua中的函数是“第一类值”,就是说函数和整数,字符串这些是一样的,都可以保存到变量中,看上面第一句的声明。
- 初看上去,由于创建变量i的函数newCounter已经返回,所以之后每次调用匿名函数时,i都应是超出作用返回的。其实不然,Lua以closure概念处理这种情况,一个closure就是一个函数加上它访问的所有“非局部的变量”。上例中内部函数counter 的非局部变量就是i和参数add,不管c1访问多少次,都能取到这些非局部变量的值。
5. 非全局函数
6. 真确的尾调用(tail call)
Lua函数有一个特点:那就是Lua支持“尾调用消除” :尾调用消除就是一种类似于goto的函数调用。当一个函数f末尾调用其他函数g时,称为“尾调用”。也就说,当调用完g之后,f函数没有其他代码需要执行。这种情况,程序也不需要保存任何关于改函数的栈(stack)信息了。lua语言的尾调用不消耗任何的栈空间。
由于Lua函数尾调用不会消耗栈空间,所以一个程序可以拥有无限潜逃的尾调用。
function f(x) g(x) end --不算,g(x)后需要舍弃临时结果
return g(x)+ --必须做一次加法
return x or g(x) --必须调整为一个返回值 正确的尾调用:
return <function>(<args>)
没有“尾调用消除”的话,每次调用都会创建一个新的栈层(stack level).
Lua学习(4)——函数的更多相关文章
- lua学习之函数篇
函数 函数是对语句和表达式进行抽象的主要机制 两种用法 一是可以完成特定的任务,一句函数调用被视为一条语句 二是以只用来计算并返回特定的结果,视为一句表达式 print("Hello, Wo ...
- Lua 学习 chapter30 编写c函数的技巧 - Jow的博客
目录 数组操作 字符串操作 在c函数中保存状态 生活总需要一点仪式感,然后慢慢的像那个趋向完美的自己靠近. 数组操作 Lua中的数组就是以特殊的方式使用边.像lua_setttable and lua ...
- Lua 学习笔记(五)函数
函数的定义:在Lua中,函数是一种对语句和表达式进行抽象的主要机制. 一.函数基本用法 在Lua中, 1.函数既可以完成某项特定的任务.(被视为一条语句) 2.也可以 ...
- lua操作常用函数学习一
(1)lua 和 C++之间的交互的基本知识: lua 和 C++ 之间的数据交互通过堆栈进行,栈中的数据通过索引值进行定位,(栈就像是一个容器一样,放进去的东西都要有标号)其中栈顶是-1,栈底是1, ...
- Lua学习笔记(三):函数和闭包
函数 lua的函数以function关键字开始,后跟函数名称和参数,最后以end结束,我们看一个简单的函数定义: function foo() --do something end function ...
- Lua学习笔记(6): 函数
Lua的函数 函数用于简化程序,当某些工作需要重复执行的时候就可以使用函数减轻工作量(虽然复制粘贴也行) 语法: function 函数名(参数列表) 函数体 return 返回值 end --结束标 ...
- Lua 学习之基础篇二<Lua 数据类型以及函数库 汇总>
引言 前面讲了运算符,这里主要对Lua的数据处理相关的数据类型和函数库进行总结归纳,后面会再接着单独分开讲解具体使用. 首先因为Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值. 值可以存储 ...
- [转]LUA 学习笔记
Lua 学习笔记 入门级 一.环境配置 方式一: 1.资源下载http://www.lua.org/download.html 2.用src中的源码创建了一个工程,注释调luac.c中main函数,生 ...
- Lua学习笔记(二):基本语法
Lua学习指南:http://www.lua.org/manual/ 首先我们要明确的一点是:在Lua中,除了关键字外一切都是变量. Lua关键字 可以查看这个地址:http://www.lua.or ...
随机推荐
- 【转】windows浏览共享切换用户登录的方法
1.打开 “我的电脑” 单击 菜单栏“工具”,选择“映射网络驱动器” ,单击“使用其他用户名”,在弹出的对话框之中输入用户名.密码2.遇到提示“您已经建立连接,不能重复连接”类似信息的时候,在开始-运 ...
- 关于C++ 循环
有的时分,可能需求屡次履行同一块代码.通常情况下,句子是顺序履行的:函数中的第一个句子先履行,接着是第二个句子,依此类推. 编程言语供给了答应更为杂乱的履行途径的多种操控结构. 循环句子答应咱们屡次履 ...
- 学Java,是自学还是去培训班学习?
现在正在读在校的最后一个学年,想毕业后从事编程,但是感觉自己技术太差,应该是培训呢?还是去找实习?亦或是有更好的途径? 对于 Android 目前的行业趋势,不知道自己该不该坚持?还是转其他行业? 已 ...
- 通过VMware安装Linux操作系统
1.安装好vmvare,下载好Linux,本文采用redhat 6.5 (下载linux可参考http://www.linuxidc.com/Linux/2007-09/7399.htm) 2.选择 ...
- c的旅程---字符
输出菱形实验: /***************** 2017年四月十六. 第一个例子,输出菱形.就是找关系. 这是当n= 3时, * *** * ******************/ #inclu ...
- 在同一个系统上装两个不同版本的jdk,配置环境变量不起作用,jdk版本的切换问题
本人这台笔记本前面装了jdk8,现在准备用jdk7,我安装好了jdk7:把系统变量中的JAVA_HOME 改为 D:\java\jdk\jdk7\jdk1.7.0_67,Path 下添加如下变量,记得 ...
- Mac os下安装brew
1.首先没下载xcode,请先安装xcode,安装的继续往下面看 2.安装brew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubuser ...
- [Day02] int, str功能学习
第二天任务: int的常用功能,参照该篇博客里面列举的常用功能 http://13683137989.blog.51cto.com/9636221/1911393 str的常用功能(重要) ,参照该篇 ...
- Python中使用Mysql(安装篇)
准备工作 import MySQLdb Linux系统自带了Python,但并不是都有这个包,至少我每次拿到一台全新的服务器时候,都发现没有装这个包. 这个东西的下载地址是 http://source ...
- apache配置多个站点
序:这次项目主要是为了给微信客户端添加一个地址,在微信公众号里面添加一个可以访问的app下载页面,说起来很简单,但总不能为了这么小的一个网站新建一个web服务器吧! 现在开始配置,首先必须确认已经在L ...