Lua学习笔记之函数、变长参数、closure(闭包)、
1. Lua函数支持多返回值,但并不是每次调用函数返回的全部值都会被使用。
一、函数:
有一条规则是只有当函数调用是表达式最后一个元素时,才会使用它的全部返回值。看代码:
在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
在以上声明中,包含了函数名(add),参数列表(a),以及函数体。需要说明的是,Lua中实参和形参的数量可以不一致,一旦出现这种情况,Lua的处理规则等同于多重赋值,即实参多于形参,多出的部分被忽略,如果相反,没有被初始化的形参的缺省值为nil。
复制代码 代码如下:
1.
多重返回值:
Lua支持返回多个结果值。如:
--string.find函数返回两个值,:被查找子串的开始索引和结束索引
s,e = string.find("Lua program language","Lua")
print(s,e) --> 1 3
--如果找不到,则输出nil和nil
s,e = string.find("Lua program language","Lub")
print(s,e) -->nil nil
--找出数组中最大的元素和其索引
function maximum(a)
local mi = 1 --最大元素索引,开始假设第一个元素就是最大元素
local m = a[mi]
for i,val in ipairs(a) do
if m < val then
mi,m = i,val
end
end
return mi,m
end
print(maximum{1,2,10,4,5,7}) --> 3 10
--返回多个值的函数只有作为表达式最有一个元素时才能使用它返回的多个值
--否则只取第一个值
--定义一个返回两个值的函数
function foo() return "a","b" end
--foo()在表达式最后,使用了他返回的两个值
a,b = foo() -->a b
print(a,b)
--foo()出现在表达式中间, 只使用了她返回的第一个值
a,b,c = foo(),"c"
print(a,b,c) -->a c nil
--使用了函数返回的两个结果
print(foo()) -->a b
--把函数调用放在括号中间, 迫使函数只返回的一个结果
print((foo())) --> a
1 s,e = string.find("Hello Lua users","Lua")
2 print("The begin index is " .. s .. ", the end index is " .. e .. ".");
3 -- The begin index is 7, the end index is 9.
2. 函数支持变长参数:...
如果变长参数中没有nil,那么可以使用ipairs(...)来遍历得到所有的参数.
以上的代码示例只是演示了如何获取Lua函数的多个返回值,下面的示例将给出如何声明返回多个值的Lua函数。如:
如果参数中有nil,那么就只能使用select()函数了. 因为ipairs只能遍历到nil处.
1 function maximum(a)
2 local mi = 1
3 local m = a[mi]
4 for i, val in ipairs(a) do
5 if val > m then
6 mi,m = i,val
7 end
8 end
9 return m,mi
10 end
11 print(maximum{8,10,23,12,5})
12 --23 3
复制代码 代码如下:
Lua会调整一个函数的返回值数量以适应不同的调用情况。若将函数调用作为一条单独语句时,Lua会丢弃函数的所有返回值。若将函数作为表达式的一部分来调用时,Lua只保留函数的第一个返回值。只有当一个函数调用是一系列表达式中的最后一个元素时,才能获得所有返回值。这里先给出三个样例函数,如:
function foo0() end
function foo1() return "a"
end
function foo2() return "a","b"
end
--变长参数
--使用变长参数完成对nunmber列表求和
function add(...)
local sum = 0
for i,v in ipairs(...) do
sum = sum v
end
return sum
end
print(add{1.1,2.2,3.3,4.4,nil,6,8}) -->11
说明nil后面的6,8都没有遍历到
--如果变长参数中故意传入nil
--那么就要使用select函数来访问变长参数列表了.
--select得以参数如果传入的是整数n,
返回的是第i个元素开始到最后一个元素结束的列表
--如果传入的是"#",则返回参数列表的总长度
function add2(...)
local sum = 0
local arg
for i=1,select('#',...) do
--从输出结果可见,select(i,...)
返回的是第i个元素开始到最后一个元素结束的列表
print(select(i,...)) -->2 4 6 nil 5 8
-->4 6 nil 5 8
-->6 nil 5 8
-->nil 5 8
-->5 8
-->8
--只取列表的第一个值
arg = select(i,...)
if arg then
sum = sum arg
end
end
return sum
end
print(add2(2,4,6,nil,5,8)) -->25 说明nil后边的值都遍历到了
示例代码
3.closure(闭包)
结果
我的理解是:使得内部函数能够调用外部函数的局部变量,而且在外部函数调用结束后仍然能使用外部函数的局部变量.而每次调用外部函数的会重新创建一个closure,而且以前的不会消失.这里不禁产生一个疑问:closure在什么时候释放?
注释
复制代码 代码如下:
x,y = foo2()
-- closure的特性
function newCounter()
local i = 0
return function()
i = i 1
return i
end
x = "a", y = "b"
您可能感兴趣的文章:
- oracle中变长数组varray,嵌套表,集合使用方法
- 浅谈C 内存分配及变长数组的动态分配
- C语言可变参数函数详解示例
- C/C 宏定义的可变参数详细解析
- C 可变参数的实现方法
- 关于C/C 中可变参数的详细介绍(va_list,va_start,va_arg,va_end)
- C/C 中可变参数的用法详细解析
- C 用指针变量作为函数的参数接受数组的值的问题详细总结
- C 可变参数的函数与模板实例分析
- C 中的变长参数深入理解
函数调用时最后的(或仅有的)一个表达式,Lua会保留其尽可能多的返回值,用于匹配赋值变量。
x = foo2()
x = "a", 返回值"b"被忽略
x,y,z = 10,foo2()
x = 10, y = "a", z = "b"
x,y = foo0()
x = nil, y = nil
如果一个函数没有返回值或者没有足够多的返回值,那么Lua会用nil来填补。
x,y = foo1()
x = "a", y = nil
x,y,z = foo2()
x = "a", y = "b", z = nil
x,y = foo2(),20
x = "a", y = 20
如果一个函数调用不是一系列表达式的最后一个元素,那么将只产生一个值。
x,y = foo0(),20,30
x = nil, y = 20, 30被忽略。
print(foo0())
当一个函数调用左右另一个函数调用的最后一个实参时,第一个函数的所有返回值都将作为实参传入第二个函数。
print(foo1())
a
print(foo2())
a b