lua的函数初识
2015-07-09 22:57
357 查看
学习到Lua的函数,觉得有必要记下来。
参考教程:Programming in Lua
举个例子:
这个特性可以被用来设置参数的默认值:
多重赋值时,要根据函数的调用位置来决定返回值的数目。函数调用在表达式末尾,则根据实际情况返回结果值。
无返回值或返回值数目小于多重赋值数目,则多于的值为nil。
如果函数调用不是在表达式的末尾,那么函数只返回一个结果值。
当一个函数调用是另外一个函数的最后一个参数,那么第一个函数返回的所有结果都是另一个函数的参数。
表构造能收集函数的所有返回值,不需要做出调整。
当然,这也只是针对函数处于表达式的末尾时:
形如return f()这个表达式也会返回f的所有结果值:
当然也可以通过一个括号来只返回一个结果值:
有个特别的函数table.unpack就是有多个返回值:
unpack能帮助你实现一个调用含有任意参数的任意函数机制,说白了,能实现函数的动态调用,还是看例子。
这个函数将a中的所有值作为f函数的参数。
下面看这个函数调用:
你可以动态的进行改写:
通常来说,unpack使用长度运算符来确定元素的返回数目,所以它是针对适当的序列来说的。但是如果需要,可以加以限制:
下面是用Lua函数实现的可变参数函数例子:
…这三点就是表明一个函数有可变参数。…叫做参数变量表达式,表现类似一个返回所有结果值的函数。
可以模仿函数参数传递机制:
变为:
再看:
function id (…) return … end
上面这个机制可以用来进行跟踪调试。下面是另外一个有用的例子,结合string.format与io.write函数:
注意上面的三点在fmt之后。因为Lua函数中可变参数这部分之前可以是参数数目确定的部分。
有极少数情况下,可变参数中可能有nil值,这时候{…}就不适用了。这种情况下,就要用table.pack函数,这个函数接收任意数目参数然后返回一个新的表。但是这个表有个额外的n区域,表示元素数目。
下面的例子测试是否有参数为nil:
在可变参数中不会有nil值的情况下{…}比table.pack(…)速度快多了。
这种风格的函数传递在函数有很多参数且它们其中大部分都是可选项时是非常有用的。比如GUI编程中。
参考教程:Programming in Lua
函数可以以表达式或陈述语句出现,如下所示:
print(8*9, 9/8) a = math.sin(3) + math.cos(10)
书写函数时有个小规则,如果函数只有一个参数,或者是一串字符,或者是一个表结构时,括号可以省略:
print "Hello World" <--> print("Hello World") dofile 'a.lua' <--> dofile ('a.lua') f{x=10, y=20} <--> f({x=10, y=20}) type{} <--> type({})
对于Lua的面向对象,有一个特殊的语法来使用函数,就是使用冒号:
o:foo(x)
lua函数的一般写法:
function fun_name(<parameters>) <body> end
举个例子:
-- add the elements of sequence 'a' function add (a) local sum = 0 for i = 1, #a do sum = sum + a[i] end return sum end
调用Lua函数时,传递的参数和实际参数数目可以不一样,Lua会自动调整参数匹配。如果传递的参数比实际参数多了,那么多于的会被舍弃,少于的会得到nil值。
比如有个函数有下面几种情况:f(3) --> 3 nil f(3, 4) --> 3 4 f(3, 4, 5) --> 3 4 (5 is discarded)
这个特性可以被用来设置参数的默认值:
function incCount (n) n = n or 1 count = count + n end
lua的函数可以有多个返回值
比如lua库函数string.find:s, e = string.find("hello Lua users", "Lua") print(s, e) --> 7 9
lua函数的返回值数目也可以根据函数实际调用情况进行调整
比如下面三个函数:function foo0 () end -- returns no results function foo1 () return "a" end -- returns 1 result function foo2 () return "a", "b" end -- returns 2 results
多重赋值时,要根据函数的调用位置来决定返回值的数目。函数调用在表达式末尾,则根据实际情况返回结果值。
x,y = foo2() -- x="a", y="b" x = foo2() -- x="a", "b" is discarded x,y,z = 10,foo2() -- x=10, y="a", z="b"
无返回值或返回值数目小于多重赋值数目,则多于的值为nil。
x,y = foo0() -- x=nil, y=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 is discarded
当一个函数调用是另外一个函数的最后一个参数,那么第一个函数返回的所有结果都是另一个函数的参数。
print(foo0()) --> print(foo1()) --> a print(foo2()) --> a b print(foo2(), 1) --> a 1 print(foo2() .. "x") --> ax (see next)
表构造能收集函数的所有返回值,不需要做出调整。
t = {foo0()} -- t = {} (an empty table) t = {foo1()} -- t = {"a"} t = {foo2()} -- t = {"a", "b"}
当然,这也只是针对函数处于表达式的末尾时:
t = {foo0(), foo2(), 4} -- t[1] = nil, t[2] = "a", t[3] = 4
形如return f()这个表达式也会返回f的所有结果值:
function foo (i) if i == 0 then return foo0() elseif i == 1 then return foo1() elseif i == 2 then return foo2() end end print(foo(1)) --> a print(foo(2)) --> a b print(foo(0)) -- (no results) print(foo(3)) -- (no results)
当然也可以通过一个括号来只返回一个结果值:
print((foo0())) --> nil print((foo1())) --> a print((foo2())) --> a
有个特别的函数table.unpack就是有多个返回值:
print(table.unpack{10,20,30}) --> 10 20 30 a,b = table.unpack{10,20,30} -- a=10, b=20, 30 is discarded
unpack能帮助你实现一个调用含有任意参数的任意函数机制,说白了,能实现函数的动态调用,还是看例子。
f(table.unpack(a))
这个函数将a中的所有值作为f函数的参数。
下面看这个函数调用:
print(string.find("hello", "ll"))
你可以动态的进行改写:
f = string.find a = {"hello", "ll"} print(f(table.unpack(a)))
通常来说,unpack使用长度运算符来确定元素的返回数目,所以它是针对适当的序列来说的。但是如果需要,可以加以限制:
print(table.unpack({"Sun", "Mon", "Tue", "Wed"}, 2, 3)) --> Mon Tue
参数可变的函数
lua的函数可以拥有可变参数,也就是参数数目可变。print就是这样一个函数。下面是用Lua函数实现的可变参数函数例子:
function add (...) local s = 0 for i, v in ipairs{...} do s = s + v end return s end print(add(3, 4, 10, 25, 12)) --> 54
…这三点就是表明一个函数有可变参数。…叫做参数变量表达式,表现类似一个返回所有结果值的函数。
可以模仿函数参数传递机制:
function foo (a, b, c)
变为:
function foo (...) local a, b, c = ...
再看:
function id (…) return … end
function foo1 (...) print("calling foo:", ...) return foo(...) end
上面这个机制可以用来进行跟踪调试。下面是另外一个有用的例子,结合string.format与io.write函数:
function fwrite (fmt, ...) return io.write(string.format(fmt, ...)) end
注意上面的三点在fmt之后。因为Lua函数中可变参数这部分之前可以是参数数目确定的部分。
CALL PARAMETERS fwrite() fmt = nil, no extra arguments fwrite("a") fmt = "a", no extras fwrite("%d%d", 4, 5) fmt = "%d%d", extras = 4 and 5
有极少数情况下,可变参数中可能有nil值,这时候{…}就不适用了。这种情况下,就要用table.pack函数,这个函数接收任意数目参数然后返回一个新的表。但是这个表有个额外的n区域,表示元素数目。
下面的例子测试是否有参数为nil:
function nonils (...) local arg = table.pack(...) for i = 1, arg.n do if arg[i] == nil then return false end end return true end print(nonils(2,3,nil)) --> false print(nonils(2,3)) --> true print(nonils()) --> true print(nonils(nil)) --> false
在可变参数中不会有nil值的情况下{…}比table.pack(…)速度快多了。
命名参数
Lua中函数参数传递是基于位置的。但是,也可以通过名字来定义参数,这在某些时候很有用,比如os.rename函数,对一个文件重命名。通常,我们不知道哪个文件名在前。这是,通过名字就很有用了:rename{old="temp.lua", new="temp1.lua"} function rename (arg) return os.rename(arg.old, arg.new) end
这种风格的函数传递在函数有很多参数且它们其中大部分都是可选项时是非常有用的。比如GUI编程中。
相关文章推荐
- Evaluate Reverse Polish Notation
- Lua与c/c++交互
- lua string
- lua语法入门
- quick-3.5 lua调用c++
- angluar去掉url中#
- 第1章 Lua基础
- lua
- Lua编程示例(八):生产者-消费者问题
- Lua脚本之语法基础快速入门
- Lua编程示例(七):协同程序基础逻辑
- Lua编程示例(六): C语言调用Lua函数
- Lua编程示例(五): C语言对Lua表的读取和添加
- lua的几个时间相关处理函数
- Lua编程示例(三):稀疏表、双端队列、格式化输出、表和循环表的格式化输出
- Lua编程示例(二):面向对象、metatable对表进行扩展
- Lua编程示例(一):select、debug、可变参数、table操作、error
- Lua函数用法研究
- lua 安装配置
- Lua中调用C++函数示例