Programming in Lua, 2nd edition - Chapter 5: Functions

本文介绍了Lua中的函数使用,包括函数的调用方式、多返回值、可变参数、默认参数以及以表为参数的命名参数。通过实例展示了如`print`、`math`库函数、`os.date`等的使用,还讨论了如何利用`unpack`函数实现泛型调用和参数动态传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

Chapter 5: Functions

 

 

print(8*9, 9/8)

a = math.sin(3) + math.cos(10)

print(os.date())

 

一此特殊情况下,函数可以不带括号

 

函数只有一个参数,并且这个参数是string,或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({})

 

 

object-oriented calls

 

o:foo(x) o.foo(o,x) 的另一种写法。

 

参见16

 


 

函数的实参比形参少用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 is discarded)

 

 

函数的这种行为会带来默认参数的效果

 

以下例子调用incCount() 相当于调用incCount(1)

 

function incCount (n)

n = n or 1

count = count + n

end

 

 


 

5.1 Multiple Results

 

函数的多返回值

 

string.find 函数会返回两个值,第一个是成功匹配的开始索引,第二个是结束索引

 

s, e = string.find("hello Lua users", "Lua")

print(s, e) --> 7 9

 

 

以下函数返回找到的最大值及其在表中的索引

 

function maximum (a)

local mi = 1 -- index of the maximum value

local m = a[mi] -- maximum value

for i,val in ipairs(a) do

if val > m then

mi = i; m = val

end

end

return m, mi

end

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

 

 

用多赋值的形式接收函数的多返回值

 

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"

 

x,y = foo0()                        -- x=nil, y=nil           -- 少则补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)

 

 

用函数的返回值构造表

 

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   -- 函数不是表的最后一个参数

 

 

根椐函数实参的不同,让其调用其它不同的函数

 

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 后面是不需要括号的,return(f(x)) 总是只会返回一个值

 

 

特殊的多返回值函数unpack.

 

unpack 函数以一个数组作为参数(也是表),返回数组的所有元素

 

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(unpack(a))

 

 

string.find("hello","ll") 的另一种写法:

 

f = string.find

a = {"hello", "ll"}

f(unpack(a))

 

 

 

 

 

 

 

内置函数unpack 实际上是C 实现的,下面是lua 实现

 

unpack 函数的lua 递归实现

 

function unpack (t, i)

i = i or 1

if t[i] then

return t[i], unpack(t, i + 1)

end

end

 

 

5.2 Variable Number of Arguments

 

参数数量可变的函数 函数

 

以下函数返回其所有参数的和

 

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 = ...

 

 

function foo (a, b, c) 的另一种写法

 

function foo (...)

local a, b, c = ...

 

 

 

 

返回所有传进来的参数的函数

 

function id (...) return ... end

 

先打印其所有参数然后在工作的函数

 

function foo1 (...)

print("calling foo:", ...)

return foo(...)

end

 

 

一个更有用的例子

 

function fwrite (fmt, ...)

return io.write(string.format(fmt, ...))

end

 

fwrite() fmt = nil, no varargs

fwrite("a") fmt = "a", no varargs

fwrite("%d%d", 4, 5) fmt = "%d%d", varargs = 4 and 5

 

 

select 函数

 

函数的所有参数

 

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

local arg = select(i, ...) -- get i-th parameter

<loop body>

end

 

select 函数的第一个参数只能是’#’ 或一个数字nselect('#', ...) 返回中所有参数的个数(包含nil)select(n, ...) 则返回中第n 个参数

 

 


 

5.3 Named Arguments

 

以一个表作为参数的函数

 

function rename (arg)

return os.rename(arg.old, arg.new)

end

 

name={old="temp.lua", new="temp1.lua"}

rename(name)

 

某种状况下,这种风格的参数传递特别有用,比如说一个函数有大量参数,而且多数是可选参数。

 

 

function Window (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

--  给可选参数自动赋默认值

_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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值