Lua极简入门(六)——函数的参数

函数定义完成后,那么函数的调用方式,完成的功能,以及返回值都将固定。此时就剩下调用了,对于调用函数,只需要关注参数,并按要求设置参数,并接收返回值,这样函数的整个流程就完成了。

在Lua中,支持可变参数定义,即在函数使用过程中,传递的参数是可以变化的,可不传、传递一个、两个等等。比如需要计算一组数字的累加,那么数字的个数是不固定的。通常会定义一个函数,接收一个table,将不固定的数字存储到table中,并作为实参传入到函数中,实现累加需求:

function adds(numbers)
    total = 0
    for i, v in pairs(numbers) do
        total = total + v
    end

    return total
end

函数定义完成后,在使用之前,先将数字添加到一个table中,之后完成调用

nums = { 1, 2, 3 }
t = adds(nums)
print(t)
-->> 6
nums = { 1, 2, 3, 4 }
t = adds(nums)
print(t)
-->> 10

以上按传统的方式实现了不固定数字的累加函数定义。对于Lua,可以使用可变参数的定义方法,完成不固定数字累加的方法,这种实现及调用时更加方便,毕竟不用在声明table并组织参数:

function adds(...)
    total = 0
    for i, v in pairs({ ... }) do
        total = total + v
    end

    return total
end

上面Lua的可变参数定义,与传统函数(参数为table)定义方式相比,基本上一致,只是将参数table变更为了...三个点。虽然函数定义时,没有太大变化,但是在调用时,将完全不同。

print(adds())
-->> 0
print(adds(1, 2, 3))
-->> 6
print(adds(1, 2, 3, 4))
-->> 10

参数中的3个点... 表示该函数可接受不同数量的参数。当调用时,所有的参数都会被收集起来,当访问可变参数时,仍然使用3个点表示,...在使用时,作为一个表达式,如上述中的{...},当使用{}标记可变参数时,则将其转换为了一个table

三个点...作为表达式,可以在函数中直接使用,但在使用时,会将所有的可变参数全部返回。

function adds(...)
    local a, b = ...
    print(a, b)
end

adds(1, 2)      -- 读取可变参数,并赋值给a,b
-->> 1  2
adds(3, 4, 5)   -- 读取可变参数,并赋值给a,b,5将会被丢弃
-->> 3  4

在定义函数过程中,可变参数也可以和固定位置的参数混用,但可变参数必须在最后位置。

function adds(name, ...)
    if name ~= nil then
        print("name=" .. name)
    end
    print(...)
end

adds()          -- name 和 可变参数均为nil
adds(1)         -- name=1,可变参数为nil
-->> name=1
adds(1, 2, 3)   -- name=1,可变参数为2,3
-->> name=1
-->> 2  3

在前面,已经使用可变参数...作为表达式,将其值全部返回,并赋给新的变量;也可以将可变参数转为数组{...},并遍历使用可变参数。Lua在这两种读取可变参数之外,还提供了select函数,用于访问变长参数。该函数的定义方式为select(index,...),即第一个位置为固定参数,值包含两种取值:number#,如果传递数值,则表示获取可变参数指定位置的参数,如果为#,则返回可变参数的长度;第二个参数为可变参数本身,仍使用...表示。

function adds(...)
    for i, v in pairs({ ... }) do
        print(v)
    end
end
adds(1, 2, nil, 4)
-->> 1
-->> 2
-->> 4

上述中,无法使用table获取到传递的nil。为了解决这个问题,可以使用select以便获取参数总长度,以及指定位置的参数。

function adds(...)
    local i = select(2, ...)
    print(i)
    local i = select(3, ...)
    print(i)
    local len = select("#", ...)    -- 获取可变参数的长度
    print(len)
end

adds(1, 2, nil, 4)
-->> 2
-->> nil
-->> 4

可变参数,在使用过程中,当作为表达式时,完全等价于原始可变参数,因此可变参数,在一些需要记录日志时,有着非常良好的应用场景,比如类似于Spring切面记录日志的方式,可以使用Lua的可变参数来进行模拟

function adds(...)
    total = 0
    for i, v in pairs({...}) do
        total = total + v
    end

    return total
end

function log(...)
    print("执行累加操作")
    return adds(...)
end

t = log(adds(1, 2, 3, 4))
print(t)
-->> 执行累加操作
-->> 10

在Python中,有一种关键词参数,在调用时允许使用关键字对参数进行限定,并提供必要的检查手段,对于程序的扩展,有着良好的作用,如下:

def call(name,**kw):
    pass

call("ray", language='java', position='beijing')

在Lua中,并不具备命名参数的功能,但是可以使用table进行模拟实现,并且当参数只有一个时,Lua允许直接跟table,因此从实用上可以实现类似的效果。

function worker(employee)
    -- 必须具备姓名,开发语言,以及工作年限
    if not employee.name or type(employee.name) ~= "string" then
        error("员工必须具备姓名")
    end
    if type(employee.language) ~= "string" then
        error("必须具备开发语言")
    end
    if type(employee.workingYears) ~= "number" then
        error("需要工作年限")
    end
    -- 还有其他属性,如籍贯省市,月薪等
    print(employee.province)
    print(employee.city)
    print(employee.salary)
end

worker{
    name = "ray",
    language = "java",
    workingYears = 10,
    province = "beiijng",
    city = "beijing"
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,781评论 0 38
  • 函数有两种用途: 完成指定任务,此时函数作为调用语句使用。 计算并返回值,此时函数作为赋值语句的表达式使用。 调用...
    JunChow520阅读 3,747评论 0 3
  • 注:lua5.0以上版本去除了table.getn方法,可以用#tableName代替 函数有两种用途:1.完成指...
    _小圆球_阅读 638评论 1 1
  • 天天洗一次头是平时保养头发必不可少的一个过程,置信许多人都不会觉得生疏。白昼任务忙碌,许多人都喜爱早晨洗头或挑选晚...
    wuwu35阅读 575评论 0 0
  • 人类自诞生以来,从我们呱呱坠地开始,没有一个人不希望自已成为优秀的人,婴儿哇哇嗷叫,付出努力,希望吸引妈妈的关切,...
    北海棠阅读 577评论 0 2