伟人之所以伟大,是因为他与别人共处逆境时,别人失去了信心,他却下决心实现自己的目标。
在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。
Lua 函数主要有两种用途:
1.完成指定的任务,这种情况下函数作为调用语句使用;
2.计算并返回值,这种情况下函数作为赋值语句的表达式使用
Lua 编程语言函数定义格式如下:
optional_function_scope function function_name( argument1, argument2, ...)
function_body
return result_params_comma_separated
end
解析:
optional_function_scope: 该参数是可选的制定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。
function_name: 指定函数名称。
argument1, argument2, ...: 函数参数,多个参数以逗号隔开,函数也可以不带参数。
function_body: 函数体,函数中需要执行的代码语句块。
result_params_comma_separated: 函数返回值,
代码:
--加法计算
--add 函数名 arg1,arg2参数 ,end函数块的结束符
--a,b 要传到函数的参数
--add(a,b) 调用函数
local function add(arg1,arg2)
print( arg1 + arg2)
end
local a = 1
local b = 1
add(a,b) --调用add函数
--->2
--比较两个数 并打印数值最大的
local max = 0
local function Max(arg1,arg2)
local result = nil
if arg1 > arg2 then
result = "the max is arg1"..arg1
elseif arg1 < arg2 then
result = "the max is arg2:"..arg2
else
result = arg1 or arg2
result = "arg1 等于 arg2 :"..result
end
return result
end
local a,b = 12,14
max = Max(a,b)
print(max)
--->the max is arg2:14
多返回值
Lua语言函数可以返回多个值,每个值以逗号隔开。
local function getNum(arg1,arg2)
local max = 0
local min = 0
if arg1 ~= arg2 then
if arg1 > arg2 then
max = arg1
min = arg2
else
max = arg2
min = arg1
end
else
max = arg1 or arg2
return max
end
return max,min --两个返回值
end
local maxNum,minNum = getNum(3,2) --两个变量对应接收赋值
print(maxNum,minNum)
--结果:3,2
可变参数
Lua 函数可以接受可变数目的参数,在函数参数列表中使用三点 ... 表示函数有可变的参数
...即表示 一个,两个或者多个参数
如下代码
--代表一个参数的情况
local function getNum(...)
--打印参数
print(...)
end
getNum(1)
--运行结果:1
--代表多个参数的情况下需要做成参数数组 然后 分别打印
local function getNum(...)
--用大括号包起来 转成 参数 数组,然后用for迭代器打印参数
local ArgArray = {...}
for k, v in pairs(ArgArray) do
print(v)
end
end
getNum(1,2,3,4)
--运行结果:1 2 3 4
注意:
--[[
1,所有的函数最后都有一个隐藏的return,因此不必显示书写此语句,除非需要 根据条件 中断某语句 或者返回需要的值。
2,函数作为参数如果不写括号 则 传入的是该函数的地址;如果带括号 则先运行该函数
3,该函数如果是作为print的参数带括号,则先运行该函数,然后打印该函数的返回值,如果没有返回值则打印空行
]]
local function func()
print("aa")
return 1
end
print(func())
--结果:aa 1
-------------------
local function func()
print("aa")
return
end
print(func())
--结果:aa
-------------------
local function func()
print("aa")
return 1
end
print(func)
--结果:function: 0x7f9698c06430
尾调用 (又称做尾调用消除)
尾调用不会占用栈的空间 所以用起来大大节省内存
语法格式
function foo()
return foo()
end
函数结尾 形如 return functionname()的 写法 叫做尾调用
代码:
local i = 1
local function foo()
i = i+1
print("the function is foo"..i)
return foo()
end
foo()
结果:
一直打印一段话 却不会卡死
尾调用优化
尾调用之所以与其他调用不同,就在于它的特殊的调用位置。函数调用会在内存形成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息。
如果在函数A的内部调用函数B,那么在A的调用记录上方,还会形成一个B的调用记录。等到B运行结束,将结果返回到A,B的调用记录才会消失。
如果函数B内部还调用函数C,那就还有一个C的调用记录栈,以此类推。所有的调用记录,就形成一个"调用栈"(call stack)。
而尾调用时,由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。
function a() {
let m = 1;
let n = 2;
return f(m + n);
}
//等同于
function a() {
return f(3);
}
//等同于
f(3);
上面代码中,如果函数f()不是尾调用,函数a()就需要保存内部变量m和n的值、f()的调用位置等信息。
但由于调用f()之后,函数a()就结束了,所以执行到最后一步,完全可以删除a() 的调用记录,只保留f(3)的调用记录。
这就叫做"尾调用优化"(Tail call optimization),即只保留内层函数的调用记录。
如果所有函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,这将大大节省内存。这就是"尾调用优化"的意义。
网友评论