【Lua学习笔记6】Lua中的函数

1,080 阅读3分钟

函数声明

function hello() 
    print('hello Lua')
end
hello()

注意,lua中的函数,不能用{}包起来,不然会报错的。

返回多个值

function test() 
    return 1, 2
end
test()

可变参数

function log(...) 
    -- 这里必须要这样赋值下,不过看官方文档里面好像没有这句,我自己跑没有这句报错
    local arg = {...}
    print('参数长度:' .. select('#', ...)) --> 参数长度:4
    print('第一个参数:' .. select(1, ...)) --> 第一个参数:1
    for k,v in ipairs(arg) do
        print(k .. v)
    end
end
log(1,2,3,4)

这里使用了lua中内置的一个函数select,select('#', ...) 表示获取参数的个数, select(n, ...) 表示获取可变参数中的第n个参数的值。

闭包

对,没错,就是js里面你理解的那个闭包,举个例子就行。

function createCounter() 
    i = 1; 
    return function() 
                i = i + 1
                return i
           end
end
counter = createCounter()
print(counter())   --> 2
print(counter())   --> 3
print(i) --> 3

注意上面的i是全局变量,如果你只想i在函数内部访问,使用local关键字来声明一个局部变量。

非全局函数

上面我们定义的其实都是全局函数,那怎么定义非全局函数呢?想想之前说过的table,我们可以在一个table对象上定义函数属性,这样来实现我们的效果。

方式一:

Lib = {
    fun1 = function() return 1 end,
    fun2 = function() return 2 end
}
print(Lib.fun1())  --> 1
print(Lib.fun2())  --> 2

方式二:

Lib = {
}
Lib.fun1 = function() return 1 end
Lib.fun2 = function() return 2 end
print(Lib.fun1())  --> 1
print(Lib.fun2())  --> 2

这个是不是跟js里面的对象很相似?

除了上面这种写法之外,Lua中还支持另外一种特殊的方式:

方式三:

Lib = {
}
function Lib.fun1() return 1 end
function Lib.fun2() return 2 end
print(Lib.fun1())  --> 1
print(Lib.fun2())  --> 2

我们也可以将函数存储到一个局部变量中,这样这个函数的作用范围就是跟这个局部变量一样的范围了。

do
local fun1 = function()
    return 1
    end
print(fun1())  --> 1
end

这里定义的fun1,只能在当前的do end块中可以访问到,外部无法访问。

定义局部函数lua中还支持另外一种方式:

do
local function fun1()
    return 1
    end
print(fun1())  --> 1
end

这两种方式一般情况下是等价的,除了递归。

来看个例子:

local fact = function (n)
    if n == 0 then return 1
    else return n*fact(n-1)   -- 会报错
    end
end

官方文档里面的说法是,在编译函数的时候,会发现fact此时还没有声明,然后报错。

下面这种方式就没有问题。

local function fact (n)
    if n == 0 then return 1
    else return n*fact(n-1)
    end
end

当然,如果你非要像上面那样写,怎么办呢?也是可以的:

local fact
fact = function (n)
    if n == 0 then return 1
    else return n*fact(n-1)   -- 会报错
    end
end

就会先声明该函数变量,这个时候编译的时候就不会报错了,运行时函数变量已经赋值过了,所以不会有问题。

尾调用优化

function g() return 1;
function f() {
    return g()
}

lua里面也有尾调用优化,如果不知道什么是尾调用优化,建议参考阮一峰老师的这篇文章 www.ruanyifeng.com/blog/2015/0… 尾调用优化就是说,如果函数结束的时候调用另外一个函数,那么就可以进行尾调用优化,就不需要保存当前函数的执行栈信息,因为这些信息后面根本用不到了。