Lua基础 函数(一)
转自: http://blog.csdn.net/wzzfeitian/article/details/8653101
在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。下面有3个例子,分别将函数当作一条语句;当作表达式(后面两个是一类)。
- print(8*9, 9/8) --> 72 1.125
- a = math.sin(3) + math.cos(10) --> a = -0.69795152101659
- print(os.date()) --> Sat Mar 9 12:14:08 2013
函数如果带参数,那么就要用(arg1, arg2,...)括起来,如果没有参数,就写个空(),说明这是个函数调用。
特例,如果函数只有一个参数,并且参数类型是字符串或者table,那么()可以省略,如下示例:
- print "Hello World" <==> print("Hello World")
- dofile 'a.lua' <==> dofile('a.lua')
- print[[a multi-line <==> print([[a multi-line
- message]] message]])
- f{x=10, y=20} <==> f({x=10, y=20})
- type{} <==> type({})
Lua支持面向对象,操作符为冒号‘:’。o:foo(x) <==> o.foo(o, x),这个在后面会专门写一篇文章。
Lua程序可以调用C语言或者Lua实现的函数。Lua基础库中的所有函数都是用C实现的。调用一个用C实现的函数,和调用一个用Lua实现的函数,二者没有任何区别。
Lua函数的定义语法比较常规,如下示例:
- function add(a)
- local sum = 0
- for i, v in ipairs(a) do
- sum = sum + v
- end
- return sum
- end
函数的参数跟局部变量一样,用传入的实参来初始化,多余的实参被丢弃,多余的形参初始化为nil。示例如下:
- function f(a, b) return a or b end
- f(3) -- a=3, b=nil
- f(3, 4) -- a=3, b=4
- f(3, 4, 5) -- a=3, b=4 (5被丢弃)
虽然Lua可以处理这样的情况,但是不鼓励这种传入错误数量参数的函数调用,可能会使程序运行时有点小问题。不过,有些情况下,这个特性可以加以利用,例如下面示例的默认参数:
1.多返回值
不同于常规函数,Lua的函数可以返回多个返回值。一些Lua中预定义的函数可以返回多个返回值。例如string.find函数,在string中匹配一个sub-string,string.find返回sub-string的起始位置和结束位置。利用多赋值语句来获取函数的多个返回值。
用Lua写的函数也可以返回多个返回值,如下示例,查找array中的最大值,并返回其位置和值
Lua会根据实际情况来使函数的返回值个数适应调用处的期望。
1)如果一个函数调用作为一条语句,所有的返回值都被丢弃
2)如果一个函数调用作为一个表达式,除了3)的情况,返回值只保留第一个
3)在多赋值,返回值作为实参来调用其他函数,table中,return语句中,这4种调用场景,如果函数调用作为其最后一个表达式,那么会保留所有的返回值,然后根据实际调用需要再纠正。
示例:
- -- 多赋值,函数调用是最后一个表达式
- 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"
- 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(1, foo2()) --> 1 a b
- print(foo2() .. "x") --> ax (see next)
- -- table中
- t = {foo0()} -- t = {} (an empty table)
- t = {foo1()} -- t = {"a"}
- t = {foo2()} -- t = {"a", "b"}
- -- table中,但是函数调用不是最后一个表达式
- t = {foo0(), foo2(), 4} -- t[1] = nil, t[2] = "a", t[3] = 4
- -- return语句中
- 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
因此,括号千万别乱用,尤其是return后的值,如果用了括号,那么就只返回一个值。
函数unpack可以返回多个值,它传入一个array,然后返回array中的每一个值。
- print(unpack{10,20,30}) --> 10 20 30
- a,b = unpack{10,20,30} -- a=10, b=20, 30 is discarded
unpack的一个重要用法是泛型调用,提供了比C语言中更大的灵活性。在Lua中,如果你想调用一个函数f,传入可变数量的参数,很简单,
- f(unpack(a))
unpack返回a中的所有值,并传给f 作为参数,下面示例:
- f = string.find
- a = {"hello", "ll"}
- print(f(unpack(a))) --> 3 4
Lua中的unpack是用C实现的。其实我们也可以用Lua来实现它
- function unpack (t, i)
- i = i or 1
- if t[i] then
- return t[i], unpack(t, i + 1)
- end
- end
2. 变参
Lua中的一些函数接受可变数量的参数,例如print函数。print函数是用C来实现的,但是我们也可以用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
参数列表中的'...'指明该函数可以接受变参。我们可以将‘...’当作一个表达式,或者一个多返回值的函数(返回当前函数的所有参数)。例如
- local a, b = ...
用可选参数的前两个初始化局部变量a,b的值。再看下面的例子,
- function foo(a, b, c) <==> function foo(...) local a, b, c = ...
- function id (...) return ... end
上面这个函数简单地返回它所有的参数。下面的例子,说明了一个跟踪函数调用的技巧
- function foo1 (...)
- print("calling foo:", ...)
- return foo(...)
- end
再看一个实用的例子。Lua提供了不同的函数来格式化文本string.formant和写文本io.write,我们可以简单地将二者合二为一。
- function fwrite (fmt, ...)
- return io.write(string.format(fmt, ...))
- end
注意有一个固定的参数fmt。变参函数可能含有不定数目的固定参数,后面再跟变参。Lua会将前面的实参赋值给这些固定参数,剩下的实参才能当作变参看待。下面是几个示例:
- CALL PARAMETERS
- fwrite() -- fmt = nil, no varargs
- fwrite("a") -- fmt = "a", no varargs
- fwrite("%d%d", 4, 5) -- fmt = "%d%d", varargs = 4 and 5
如果想要迭代处理变参,可以用{...}来将所有的变参收集到一个table中。但是有时变参中可能含有非法的nil,我们可以用select函数。select函数有一个固定的参数selector,然后跟一系列的变参。调用的时候,如果selector的值为数字n,那么select函数返回变参中的第n个参数,否则selector的值为'#',select函数会返回可变参数的总数目。下面示例:
- for i=1, select('#', ...) do
- local arg = select(i, ...) -- get i-th parameter
- <loop body>
- end
注意,select("#", ...)返回变参的数目,包括nil在内。
3. 带名字的参数
Lua中函数的参数传递是基于位置的,当调用函数的时候,实参根据位置来匹配形参。但是,有的时候,根据名字来匹配更实用。例如,系统函数os.rename,我们会经常忘记新名字和旧名字哪个在前;为了解决这个问题,我们尝试重新定义这个函数。下面这个
- -- invalid code
- rename(old="temp.lua", new="temp1.lua")
上面这个代码是非法的,Lua并不支持这样的语法。但是我们可以修改一点点,来实现相同的效果。
- function rename (arg)
- return os.rename(arg.old, arg.new)
- end
用这种方式来传递参数是很实用的,尤其是,当函数有多个参数,并且其中一些是可有可无时。例如,用GUI库创建一个新的窗口
- w = Window{ x=0, y=0, width=300, height=200,
- title = "Lua", background="blue",
- border = true
- }
Window函数可以检查必须的参数,并且给可选参数赋予默认值等。假设_Window函数可以用来创建一个新窗口,但是它必须要全部的参数。那我们就可以重新定义一个Window函数如下:
- function Window (options)
- -- check mandatory options
- if type(options.title) ~= "string" then
- error("no title")
- elseif type(options.width) ~= "number" then
- error("no width")
- elseif type(options.height) ~= "number" then
- error("no height")
- end
- -- everything else is optional
- _Window(options.title,
- options.x or 0, -- default value
- options.y or 0, -- default value
- options.width, options.height,
- options.background or "white", -- default
- options.border -- default is false (nil)
- )
- end
Lua基础 函数(一)的更多相关文章
- lua基础---函数
Lua的函数功能很强大,保留了C语言的一些基本的特性,但是也有C语言没有的特性,比如,lua可以在一个函数返回多个值,我们来看看下面这个案例: 解释运行: lua test5.lua --定义一个函数 ...
- Lua 基础
Lua 5.3 的中文手册, http://cloudwu.github.io/lua53doc 在线浏览 --第一部分 -- 两个横线开始单行的注释 --[[ 加上两个[和]表示 多行的注释. -- ...
- Lua function 函数
Lua支持面向对象,操作符为冒号‘:’.o:foo(x) <==> o.foo(o, x). Lua程序可以调用C语言或者Lua实现的函数.Lua基础库中的所有函数都是用C实现的.但这些细 ...
- Step By Step(Lua基础知识)
Step By Step(Lua基础知识) 一.基础知识: 1. 第一个程序和函数: 在目前这个学习阶段,运行Lua程序最好的方式就是通过Lua自带的解释器程序,如: /> l ...
- lua闭合函数
function count( ... ) return function( ... ) i = i+ return i end end local func = count(...) print(f ...
- 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数
[源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...
- Lua基础
局部定义与代码块: 使用local声明一个局部变量或局部函数,局部对象只在被声明的那个代码块中有效. 代码块:一个控制结构.一个函数体.一个chunk(一个文件或文本串)(Lua把chunk当做函数处 ...
- python基础——函数的参数
python基础——函数的参数 定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复 ...
- Lua基础(转)
局部定义与代码块: 使用local声明一个局部变量或局部函数,局部对象只在被声明的那个代码块中有效. 代码块:一个控制结构.一个函数体.一个chunk(一个文件或文本串)(Lua把chunk当做函数处 ...
随机推荐
- ThinkPHP中的视图二
ThinkPHP中的视图 1.模板注释 在实际项目开发中,经常要使用注释功能,如果是ThinkPHP框架,则可以在模板文件中使用如下方式进行注释: {// 注释内容 } :单行注释 {/* 注释内容 ...
- Android BroadcasetReceiver
ci@clinux:~/mp_mtk$ adb -s QGAEFYAAOFN7PNOB logcat PhoneReceiver:e *:S --------- beginning of system ...
- winform:无法引用其他类库,dll,using等个人看法【图】
在项目类库中已经引用了相关了类库,生成解决方案也没问题,但是到了后置代码,通过using引用其他类库的时候,再生成解决方案或者生成单个类库,就会报“未能找到类型或命名空间“xxx"(是否缺少 ...
- WinForm TreeView节点重绘,失去焦点的高亮显示
当用户焦点离开TreeView时,TreeView选中节点仍然高亮,但是颜色符合主题. 设置TreeView.HideSelection = False;可让选中节点保持高亮. 添加重绘事件 Tree ...
- Android:自定义控件样式(Selector)
前言 在开发一个应用程序过程中不可避免的要去修改组件的样式,比如按钮.输入框等.现在就看下如何通过Seletor实现样式的自定义.先看下简单的效果对比
- JAVA多线程学习1
一.进程与线程 线程是指进程内的一个执行单元(可理解为程序内的一条执行路径),也是进程内的可调度实体. 线程与进程的区别: 1.线程是进程的一个执行单元,一个进程可以拥有多个线程,线程之间共享进程的地 ...
- 伴随ListView、RecyclerView、ScrollView滚动滑入滑出小图标--第三方开源--FloatingActionButton
FloatingActionButton在github上的项目主页是:https://github.com/makovkastar/FloatingActionButton 它的依赖包NineOldA ...
- 关于python的环境变量问题
我的ubuntu安装python后,查看所有的环境变量,发现没有PYTHONPATH?对我使用python没太大影响,自己写的模块的路径问题有很多方法解决.但是现在我想将我写的模块放在一个包里,要用到 ...
- 8、WPF体系架构和运行机制
体系架构:http://msdn.microsoft.com/zh-cn/library/ms750441.aspx 运行机制:http://www.cnblogs.com/leep2007/arch ...
- Linux关机命令总结
在linux命令中reboot是重新启动,shutdown -r now是立即停止然后重新启动,都说他们两个是一样的,其实是有一定的区别的. shutdown命令可以安全地关闭或重启Linux系统,它 ...