Lua程序设计第二版(笔记) 第五章函数

在 Lua中,函数是一种对语句和表达式进行抽象的主要机制。函数既可以完成某项特定的任务,也可以只做一些计算并返回结果。

若一个函数只有一个参数,并且此参数是一个字面字符串或table构造式,那么圆括号可有可无。

例如:

print "hello world'

  dofile 'a.lua'

print [[a multi-line message]]

f{x = 10, y=20}

type{}

Lua为面向对象式的调用也提供了一种特殊的语法-冒号操作符。表达式o.foo(o,x)的另一种写法是o:foo(x),冒号操作符使用o.foo时隐含地作为函数的第一个参数。


Lua具有一项非常与众不同的特征,允许函数返回多个结果。只需要在 return 关键字后列出所有的返回值即可。

例如:

function maximum(a)

local mi = 1   --最大值索引

local m = a[mi] --最大值

for i, val in ipairs(a) do

if val > m then

m = val

end

end

return m, mi

end

print( maximum({8,10,23,12,5})) -- 23 2

Lua会调整一个函数的返回值数量以适应不同的调用的情况。若函数做为一条单独语句时,Lua会丢弃函数的所有返回值。若将函数以表达式的一部分来调用,Lua只保留函数

的第一个返回值。只有当一个函数调用是一系列表达式中的最后一个元素(或仅有一个元素)时 ,才能获得它的所有返回值。

"一系列表达式"在Lua中表现为4种情况:多重赋值函数调用时传入的实参列表table的构造式和return 语句

例如:

function foo0() end--无返回值

function foo1() return "a" end--返回1个结果

function foo2() return "a","b" end --返回2个结果

在多重赋值中,若一个函数调用是最后(或仅有的)一个表达式,那么Lua会保留尽可能多的返回值,用于匹配赋值变量:

x,y = foo2() --x="a", y ="b"

x = foo2() --x="a","b"被丢弃

x,y,z=10,foo2() -- x=10,y="a",z="b"

如果一个函数没有返回值或者返回没有足够多的返回值,那么Lua会用nil来补充缺失的值:

x,y = foo0() --x=nil,y=nil

x,y = foo1() --x="a",y=nil

x,y,z = fool2() --x="a",y="b",z=nil

如果一个函数调用不是一系列表达式的最后一个元素,那么将只产生一个值:

x,y =foo2(),20 -- x="a",y =20

x,y= foo0(),20,30 --x=nil,y=20, "30"被丢弃 

当一个函数调用作为另一个函数调用的最后一个(或仅有的)实参时,第一个函数的所有返回值都将作为实参传入第二个函数。

例如:

pirnt( foo0() ) 

print( foo1() ) --a

print( fool2() ) --a b

print(foo2(),1) --a 1

print( foo2() .. "x") --ax 

table构造式可以完整的接收一个函数调用的所有结果,即不会有任何数量方面的调整:

t = { foo0() } -- t = {}(一个空的table)

t = { foo1() } --t={"a"}

t = { foo2() } --t={ "a","b" }

这种行为只有当一个函数调用作为最后一个元素时才会发生,而在其他位置的函数调用总是只产生一个结果值:

t = { foo0() , foo2(), 4 } --t[1] = nil, t[2] ="a", t[3] = 4

最后一种是return语句,诸如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)) -- 无返回值

print( foo(3) ) --无返回值

可以将一个函数调用放入一对圆括号中,可以迫使它只返回一个结果:

print( ( foo2() ) ) -- a

return语句后面的内容是不需要圆括号的,在该位置上书写圆括号会导致不同的行为。

例如:

return( f(x) ),将只返回一个值,而无关乎f返回几个值。

关于多重返回值还有一个特殊函数:unpack。它接受一个数组作为参数,从下标1开始返回该数组的所有元素:

print(unpack{10,20,30}) --10,20,30

a,b = unpack{10,20,30} --a = 10, b =20 "30"被丢弃

unpack的一项重要用途体现在"泛型调用"机制中。泛型调用极致可以动态的以任何参数来调用任何函数。


变长参数

Lua中的函数还可以接受不同数量的实参。

例如:

function add( ... )

local s = 0

for i, v in ipairs{...} do

s = s+v

end

return s

end

参数表中的3个点(...)表示该函数可接受不同数量的实参。

具有变长参数的函数同样可以拥有任意数量的固定参数,但固定参数必须放在变长参数之前。

在某些特殊情况下,变长参数中可能会包含一些故意传的nil,那么此时就需要用函数select来访问变长参数了。调用select时,必须传入一个固定实参selector和一系列变长参数。如果selector为数字n,那么select返回它的第n个可变实参;否则selector只能为字符串"#",这样select会返回变长参数的总数。

例如:

for i=1, select('#', ...)

local arg = select(i, ...) -- 得到第i个参数

<循环体>

end

select('#', ... )会返回所有变长参数的总数,其中包括nil


具名实参

Lua中的参数传递机制是具有"位置性"的,也就是说在调用一个函数时,实参时通过它的参数表中的位置与形参匹配起来的。

有时候通过名称来指定实参也是很用的。Lua并不直接支持这种语法,但可以通过一种细微的改变来获得相同的效果。将素有实参组织到一个table中,并将这个table作为唯一的实参传给函数。当实参只有一个table构造时,函数调用中圆括号是可有可无的。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值