lua系统学习11-函数

函数

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

参考:

print(2)
a=mathf.sin(2);

函数的调用需要在函数名后紧跟(),当函数的唯一的参数只有一个字符串或是table构造式,那么括号就可以不需要写。
示例:

dofile "C:\\File\\Lua\\table.lua"
function funcName1(a)
    print(a)
end
funcName1 '22'
function funcName1(t)
    for i,v in ipairs(t) do
        print(i)
        print(v)
    end
end
funcName1 {"w","x"}

 return函数与块

在lua中如果在一个块内return之后出现了语句,编译器就认为他是错误代码。
如下面这个错误示例:

function returnFunc()
    return 1
    print("2")
end
print(returnFunc())

ThrowInfo:C:/File/Lua/Return.lua:8: 'end' expected (to close 'function' at line 6) near 'print'

如果有时因为调试需要 就想在return后面 写上语句,那么lua提供了return块的另一种写法。do return value end

这个写法一样不会执行return后面的语句,只是把return包起来,让其后面允许插入语句。

示例:

function returnFunc()
    do return 1 end
    print("2")
end
print(returnFunc())

函数结构

一个名称、参数列表、函数体
lua中对于函数调用时传入的实参与函数的形参不匹配的情况是包容的,不会强制报错,若是实参数量多于形参数量,则舍弃多余的实参,若是实参数量少于形参数量,那实参对应形参上剩余位置上的参数就用nil补全
测试:

function funcName2(a, b, c)
   print(a)
   print(b)
   print(c)
end
funcName2(123);
print("\n")
funcName2(1,2);
print("\n")
funcName2(1,2,3);
print("\n")
funcName2();
123
nil
nil


1
2
nil


1
2
3


nil
nil
nil

经过测试Lua不支持像C# JAVA那样的方法重载。因为在 Lua 中,由于函数参数和返回值的类型是动态的,所以无法使用函数重载机制来实现多个具有相同名称但不同参数的函数。

多重返回值

function multiplyReturn()
    return 1,2,3
end
a,b,c=multiplyReturn()
print(a)
print(b)
print(c)
1
2
3

用这种方式得到数组中的最大值以及最大值的索引。

查找最大值的示例

function FindMax(array)
    index=nil
    max=nil
    for i,v in ipairs(array) do
        if max==nil or tonumber(v)>max then
            max=tonumber(v)
            index=i
        end
    end
    return index,max
end
numArray={1,2,6,4,77,54,876,43,2}
maxPos,max=FindMax(numArray)
print("最大值的索引位置:"..maxPos)
print("最大值:"..max)

Debug

1
2
3
最大值的索引位置:7
最大值:876

lua的函数有一个特性,我觉得非常方便,充分的发挥了它弱语言的特点。

在lua中函数的返回值也不是强制的,也具有自动匹配,即:即使接受的变量与返回值 数量不一致,它也能像参数匹配一样做到自动删除,自动nil补全。

在把函数调用作为一条单独的语句的情况下(非表达式,没有左等号)lua也能执行,lua会丢弃函数的所有返回值。

示例 引入lua程序涉及第二版第五章

 

还有一种特殊情况:

x,y=func(){return 1,2},3

这种情况x,y应该对应哪个值
看示例:

function  multiplyReturnSpecial()
    return 1,2
end
x,y=multiplyReturnSpecial(),3
print("x:"..x)
print("y:"..y)
x:1
y:3

Lua编译器在编译的时候就会先根据赋值表达式逗号将左值右值进行对应。如果右值存在逗号,那么即使其中有个方法有多返回值,也会视作以一个变量接收多重返回值。

x=》multiplyReturnSpecial()
y=》3
这样单独去看x 根据Lua的参数与返回值自动匹配特性

遇到接受变量小于返回值的,会舍弃剩余的返回值。

那么最后的结构就是 留下1 舍弃2

最终x=1,y=3

当一个函数的调用作为另一个函数的参数时,原理是一样的,先拆开单独来看,就分为了 参数匹配和返回值匹配 两个步骤了。

function functionInvokeAsOtherFunArg()
    function funcName1()
        return 1,2,4
    end
    function funcName2(a,b,c)
        print(a,b,c)
    end
    print(funcName1())
    print(funcName1(22))
    funcName2(funcName1())
end
functionInvokeAsOtherFunArg();
1	2	4
1	2	4
1	2	4

在上面示例中 我们可以看到跟我们所想的是一样的,但是我又想到了一个问题,既然lua不支持方法重载,那它是怎么做到 那么多自定义数量变量的传入。难道是有一个最大的参数量,然后print那边把nil过滤掉?测试一下

print(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,2,1)

然而测试并不是这样的。
那么感觉应该也会有一个类似Params参数列表的功能?
待研究
//TODO
果然 看下面的** table列表实现变长参数和变长参数列表**

当多个返回值的函数参与到了表达式中 如计算。
那么它又是怎么处理的呢?

function functionInExpression()
    function funcName1()
        return 1,2,3
    end
    res=funcName1()+5
    print(res)
end
functionInExpression();

返回结果为6 说明它只返回了第一个返回值即 1 。
那么因此说明在参与表达式的时候 lua只会让第一个返回值参与表达式。

当然如果我们在某些情况下也想让它只返回一个返回值而且在不修改返回值的情况下,那么我们可以用圆括号包裹 函数 迫使它**只返回一个结果。**因为括号内的内容就算是一个表达式

function bracketsFunction()
    function funcName1()
return 1,2,3
    end
    print(funcName1())
    print((funcName1()))

end
bracketsFunction();

table列表实现变长参数

print函数可以接受不同数量的实参。

我们可以通过使用table构造可以接受一个函数调用的所有结果,不会有任何数量方面的调整

    function funcName1(t)
        for i, v in pairs(t) do
            print(i)
            print(v)
        end
    end
    function funcName2()
        return {x="w",y="a",1}
    end
    funcName1(funcName2())
end
ParamsList()
1
1
y
a
x
w

但是这种方式限制了 函数必须以table作为返回值,而且另一个函数也要以table作为参数。因为table是一个实例,而多重返回值返回的是多个实例。

unpack拆解列表

那么lua提供了一个中间函数可以接受一个数组或是直接是参数列表,并从下标1开始返回该数组的所有元素:

function unpackFunc()
    function funcName(a,b)
        print(a,b)
    end
    funcName(unpack {1,2,3})---复习 当函数的唯一参数是字符串或者是table构造式的时候 可以忽略圆括号
    t={222,221,220}
    funcName(unpack(t))
end
unpackFunc()
1	2
222	221

根据理解Unpack应该是把table列表所有元素都拆解出独立的一个变量了。

unpack只能写在参数列表的最后一个

unpack作为一个中间函数 传入table,然后他会将table根据多重返回值的特性把数组的所有元素将按照返回值返回。

但是这种方法需要定义一个列表,为此lua又提供了一种可以任意变长的参数列表,让无论是实参还是形参列表 都可以根据传入参数动态的指定列表的大小

变长参数列表

通过在参数中定义… 表示函数可接受不同数量的实参。
示例:

function variableNumberofARG(...)
        for i, v in ipairs({...}) do
            print("索引:"..i)
            print("值:"..v)
        end
end
variableNumberofARG(1,2,3)
number
1	2	3
索引:1
值:1
索引:2
值:2
索引:3
值:3

变长参数支持0-N的参数。一个函数需要访问这个变长参数列表的时候 也需要用到3个点,但是要通过去构造一个table去接受…的所有值。
那么有疑问了,table为什么能接受… …返回的到底是什么?
测试:

function variableNumberofARG2()
    function  multiplyReturnSpecial()
        return 1,2
    end
    for i, v in ipairs({multiplyReturnSpecial()}) do
        print("索引:"..i)
        print("值:"..v)
    end
end
variableNumberofARG2()

 

索引:1
值:1
索引:2
值:2

经过测试 …可以看作一个表达式或者是一个封装的函数,它返回的就是多重返回值,上面例子用 table来接收… 是因为这是table的特性,table支持在构造式中写上函数表达式然后把函数返回的多重返回值直接当作多个元素来构造这个表。
表达式…的行为类似与一个具有多重返回值的函数,它返回的是当前函数的所有变长参数。

function fwrite(fmt,...)
    return io.write(string.format(fmt,...))
end
fwrite("%s%d","s",3);

具名实参

具名实参就是可以在传入实参的地方用形参名称来指定具体的参数,这样就可以忽略参数的位置顺序。

但是lua中不支持具名实参,我们可以通过table来实现。
示例:

function nameArg(t)
print(t.name)
print(t.gameObject)
end
nameArg{name="Miracle",gameObject="帅哥"}
Miracle
帅哥

对于lua的这个具名的实现方式,大幅度降低了代码的可读性,本人最恶心乱代码、命名看不出实际意义的代码,像这样的引入了table,所以调用者和被调者的关系在这里被颠倒了,意思是被调用的方法反而要去依赖调用者传过来的table元素命名。 这两者就无形的形成了一种严重的耦合,被调既要知道调用,调用也要和被调达成协议。只要一个出错,全盘都错。
所以本人自己是不喜欢这种具名写法。

 

 

 

 

 

 

 

作者:Miracle
来源:麦瑞克博客
链接:https://www.unitymake.com/archives/programming-life/lua/3444
本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议,转载请注明!
THE END
分享
打赏
海报
lua系统学习11-函数
函数 在lua中,函数是一种对语句和表达式进行抽象的主要机制。函数既可以完成某项特定的人物,也可以做一些计算并返回结果。 参考: print(2) a=mathf.sin(2);……
<<上一篇
下一篇>>
文章目录
关闭
目 录