博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lua 函数
阅读量:4966 次
发布时间:2019-06-12

本文共 7592 字,大约阅读时间需要 25 分钟。

【1】函数定义

Lua函数定义格式如下:

1 optional_function_scope function function_name(argument1, argument2, argument3..., argumentn)2     function_body3 return result_params_comma_separated4 end

解析:

optional_function_scope: 该参数是可选的,指定函数是全局函数还是局部函数。

             未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。

function_name: 指定函数名称。

argument1, argument2, argument3..., argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。

function_body: 函数体,函数中需要执行的代码语句块。

result_params_comma_separated: 函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。

【2】Lua函数示例

函数示例

1 --[[ 函数返回两个值的最大值 --]] 2 local function max(num1, num2) 3    if (num1 > num2) then 4       result = num1; 5    else 6       result = num2; 7    end 8  9    return result;10 end11 12 -- 调用函数13 print("两值比较最大值为 (10, 4) :: ", max(10, 4))14 print("两值比较最大值为 (5, 6) :: ", max(5, 6))15 16 17 --[[18 两值比较最大值为 (10, 4) :: 1019 两值比较最大值为 (5, 6) ::     620 ]]

【3】Lua函数特色

(1)将函数作为参数传递给函数。示例如下:

1 --[[将函数作为参数传递给函数]] 2 myprint = function(param) 3    print("这是打印函数 - ##", param, "##") 4 end 5  6 function add(num1, num2, functionPrint) 7    result = num1 + num2 8    -- 调用传递的函数参数 9    functionPrint(result)10 end11 12 myprint(10)13 -- myprint 函数作为参数传递14 add(2, 5, myprint)15 16 --[[17 这是打印函数 - ##    10    ##18 这是打印函数 - ##    7    ##19 ]]

(2)函数可以返回多个值

例1,代码如下:

1 --[[例如:string.find 其返回匹配串“开始和结束的下标”(如果不存在匹配串返回nil)]] 2 s, e = string.find("http://www.baidu.com", "baidu") 3 print(s, e) 4  5 --[[执行结果 6 12    16 7 ]] 8  9 s, e = string.find("http://www.google.com", "baidu")10 print(s, e)11 12 --[[执行结果13 nil    nil14 ]]

例2,代码如下:

1 --[[return后列出要返回值的列表即可返回多值]] 2 function maximum (a) 3     local mi = 1             -- 最大值索引 4     local m = a[mi]          -- 最大值 5     for i,val in ipairs(a) do 6        if val > m then 7            mi = i 8            m = val 9        end10     end11     return m, mi12 end13 14 print(maximum({
8, 10, 23, 12, 5}))15 16 --[[执行结果17 23 318 ]]

例3,特殊函数unpack,它可以接受一个数组作为参数,并从下标1开始返回该数组的所有元素:

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

(3)不定形参函数

3.1 自定义不定形参函数:Lua函数可以接收可变数目的参数

1 function add(...)2 local s = 03   for i, v in ipairs{...} do   -- {...} 表示一个由所有变长参数构成的数组4     s = s + v5   end6   return s7 end8 9 print(add(3, 4, 5, 6, 7))  -- 25

3.2 将可变参数赋值给一个变量

1 --[[将可变参数赋值给一个变量]] 2 function average(...) 3    result = 0 4    local arg = {...}    -- arg 为一个表,局部变量 5    for i,v in ipairs(arg) do 6       result = result + v 7    end 8    print("总共传入 " .. #arg .. " 个数") 9    return result / #arg10 end11 12 print("平均值为", average(10, 5, 3, 4, 5, 6));13 14 --[[执行结果15 总共传入 6 个数16 平均值为    5.517 ]]

3.3 可以通过select("#", ...来获取可变参数的数量)

1 --[[可以通过 select("#",...) 来获取可变参数的数量]] 2 function average(...) 3    result = 0 4    local arg = {...} 5    for i, v in ipairs(arg) do 6       result = result + v 7    end 8    print("总共传入 " .. select("#", ...) .. " 个数") 9    return result / select("#", ...)10 end11 12 print("平均值为", average(10, 5, 3, 4, 5, 6))13 14 --[[执行结果15 总共传入 6 个数16 平均值为    5.517 ]]

3.4 需要几个固定参数再加上可变参数时,固定参数必须放在可变参数之前

1 function fwrite(fmt, ...)  -- 固定的参数fmt 2     return io.write(string.format(fmt, ...)) 3 end 4  5 fwrite("baidu\n")        -- fmt = "baidu", 没有变长参数。 6 fwrite("%d%d\n", 1, 2)   -- fmt = "%d%d", 变长参数为 1 和 2 7  8 --[[执行结果 9 baidu10 1211 ]]

3.5 遍历变长参数时只需要使用{...},然而变长参数可能会包含一些nil,那么就需要用select函数来访问变长参数。

[1] select('#', ...)返回可变参数的长度

[2] select(n, ...)用于访问n到select('#', ....)的参数

1 --[[ 2 遍历变长参数的时候只需要使用{…},然而变长参数可能会包含一些nil,那么就可以用select函数来访问变长参数了:select('#', …) 或者 select(n, …) 3 select('#', …) 返回可变参数的长度 4 select(n, …) 用于访问 n 到 select('#',…) 的参数 5 ]] 6  7 do 8     function foo(...) 9         for i = 1, select('#', ...) do  --> 获取参数总数10             local arg = select(i, ...); --> 读取参数11             print("arg", arg);12         end13     end14 15     foo(11, 12, 13, 14);16 end17 18 --[[执行结果19 arg    1120 arg    1221 arg    1322 arg    1423 ]]

(4)具名实参

具名实参,即具体名称的实参值。比如,字符串拷贝函数有两个参数(src, dest),当我们记不清第一个参数是src还是dest时,可以在调用时明确指明具体实参值。

Lua语言中的rename接口,就是个很有代表性的例子。试着新建一个文件temp.lua,然后复制以下代码段:

1 function rename(arg)2     return os.rename(arg.old, arg.new)3 end4 5 rename({old = "temp.lua", new = "temp1.lua"})6 --rename({new = "new1.lua", old = "temp1.lua"})

注意观察:执行结果,同目录下会多一个temp1.lua文件

再把第六行的注释去掉,然后执行结果:同目录下会多一个new1.lua文件。

(5)待续

【4】深入函数

(1)闭合函数

[1.1] 在Lua中,函数是第一类值

如何理解这个“第一类值”?类比着学习,我们知道C语言的数据类型有整数、浮点数、枚举、指针、数组、结构、共用体、void等等。

前面我们也学习了《》包括nil、boolean、number、string、function等等。

即就是,在Lua中,函数可以存储到变量(无论全局变量还是局部变量)中或table中,可以作为实参传递给其他函数,还可以作为其他函数的返回值。

先看最常见的这个求和函数定义:

1 function func(a, b) return a + b end

其等价于

1 func = function(a, b) return a + b end

两种方式比较:

第一种方式,似乎更符合我们对函数的潜意识(传统的)视觉印象规则。

第二种方式,更彰显了Lua中函数作为“第一类值”的体现和范畴。

通过以上两种方式的对比,我们可以更深入的理解Lua中函数的定义本质:

一个函数定义实质上是一条赋值语句,创建了一种类型为“函数”的值,且将其赋值于变量func。

可以验证一下类型,如下所示:

1 func = function(a, b) return a + b end2 print(func)            -- function: 02DF8FC83 print(type(func))      -- function4 print(func(10, 20))    -- 30

在Lua中,将表达式“function(x) <body> end”视为一种函数的构造式,就像table的构造式{ }一样。

将这种函数构造式的结果称为一个“匿名函数”,虽然一般情况下,会将函数赋予全局变量,即给予其一个名称。

但是,在某些特殊情况下,仍会需要直接用到匿名函数。

不要问我哪里需要用到,其实你肯定见过,比如sort函数,请看如下示例:

1 students = 2 { 3     {name = "Wang", age = "18"}, 4     {name = "Qin", age = "20" }, 5     {name = "Li", age = "19"}, 6     {name = "Wei", age = "21"}, 7 } 8  9 --[[ before sort ::]]10 print("before sort ::")11 for i = 1, #students do12     print(i, students[i].name, students[i].age)13 end14 15 table.sort(students, function(a, b) return (a.name > b.name) end)16 17 --[[ after sort ::]]18 print("after sort ::")19 for k, v in pairs(students) do20     print(k, v.name, v.age)21 end22 23 --[[执行结果24 before sort ::25 1    Wang    1826 2    Qin    2027 3    Li    1928 4    Wei    2129 after sort ::30 1    Wei    2131 2    Wang    1832 3    Qin    2033 4    Li    1934 ]]

像sort这样的函数,接受另一个函数作为实参,称其是一个“高阶函数”,是一种强大的编程机制。

1 names = {
"Peter", "Paul", "Mary"} 2 grades = {Mary = 10, Paul = 7, Peter = 8} 3 table.sort(names, function(n1, n2) 4 return grades[n1] > grades[n2] 5 end) 6 7 for k, v in ipairs(names) do 8 print(k, v) 9 end10 11 --[[12 1 Mary13 2 Peter14 3 Paul15 ]]16 17 names = {
"Peter", "Paul", "Mary"}18 grades = {Mary = 10, Paul = 7, Peter = 8}19 20 function sortbygrade(names, grades)21 table.sort(names, function(n1, n2)22 return grades[n1] > grades[n2]23 end)24 return names25 end26 27 for k, v in ipairs(sortbygrade(names, grades)) do28 print(k, v)29 end30 31 --[[32 1 Mary33 2 Peter34 3 Paul35 ]]36 37 --[[一般函数]]38 function increCounter1()39 local i = 040 i = i + 141 return i42 end43 44 print(increCounter1) -- function: 02A6B8F845 print(increCounter1()) -- 146 print(increCounter1()) -- 147 48 --[[闭合函数]]49 function increCounter2()50 local i = 051 return function()52 i = i + 153 return i54 end55 end56 57 print(increCounter2) -- function: 02A6B73858 print(increCounter2()) -- function: 02A6B91859 60 c1 = increCounter2()61 print(c1()) -- 162 print(c1()) -- 263 c2 = increCounter2()64 print(c2()) -- 165 print(c1()) -- 366 print(c2()) -- 267 68 --[[闭合函数 局部变量]]69 function increCounter3()70 return function()71 local i = 972 i = i + 173 return i74 end75 end76 77 print(increCounter3) -- function: 02A6B6F878 print(increCounter3()) -- function: 02A6B7D879 80 c3 = increCounter3()81 print(c3()) -- 1082 print(c3()) -- 1083 c4 = increCounter3()84 print(c4()) -- 1085 print(c4()) -- 1086 print(c4()) -- 10

匿名函数

(2)非全局函数

(3)正确尾调用

【5】总结

Good Good Study, Day Day Up.

顺序 选择 循环 总结

转载于:https://www.cnblogs.com/Braveliu/p/9682669.html

你可能感兴趣的文章
php函数fsockopen的使用
查看>>
webapi+swagger ui 文档描述
查看>>
c++ char* 与LPCTSTR相互转化
查看>>
codevs1044 拦截导弹(最长不下降子序列dp)
查看>>
AS问题解决系列1—Unable to execute DX错误
查看>>
在线任意进制转换工具 - aTool在线工具
查看>>
创建数据库
查看>>
Spark与Spring集成做web接口
查看>>
Web jquery表格组件 JQGrid 的使用 - 11.问题研究
查看>>
Ubuntu下如何访问Windows磁盘?
查看>>
Rabbitmq安装及启动 MAC系统
查看>>
nginx location配置
查看>>
在DELPHI中动态创建控件以及控件的事件(转)配合 让FIREDAC记录数据库的异常日志...
查看>>
WordPress程序文件说明
查看>>
6.6410和210的按键中断编程
查看>>
PHP处理数组和XML之间的互相转换
查看>>
办公室文员、助理都可以学学,留着迟早用得着!
查看>>
使用httpModule做权限系统
查看>>
aiohttp异步爬虫爬取当当网最热书籍并导出excel
查看>>
奇异矩阵(转载)
查看>>