BeWithYou

胡搞的技术博客

  1. 首页
  2. C/C++/Lua
  3. Lua学习笔记(二)

Lua学习笔记(二)


函数:

定义方式

function func_name(arg-list)
    ...
end


调用时 如果只有一个参数并且为字符串或table 可以不加括号传参,如print “hello”。

面向对象的语法糖 object:fun(x,y) 等价于 object.(object,x,y)

local cal = function() … end 等价于 local function cal() … end


函数传参

传参和赋值一样,少了的用nil补齐。不支持默认值,如果需要默认值可以在函数内部用 x = x or 0来显式处理。

返回值可以有多个。可以用多个变量来接受函数的多个返回值。函数外面加括号,可以强制只接收一个返回值。

unpack()一个table变量,可以返回table的所有元素,用于把table所有元素当做参数传给函数。如: fun(unpack(t))。

可变参数… ,三个点来表示。可以直接拿来用,传给下一层等等。比如,fun(a,b,c,…) 调用时fun(1,2,3,4,5,6) ...即为4,5,6。给...加上大括号,可以当成一个table用。


匿名函数,闭包:

可以声明匿名函数function() end,一般用于一次性使用,在其他函数内部当做参数,回调函数等等。

当一个函数内部嵌套另一个函数定义时,内部函数体和可以访问外部的局部变量。依赖这种词法定界的特性,可以实现闭包

function newCounter()
    local i = 0
    return function()
        i = i + 1
        return i
    end
end
c1 = newCounter()
print(c1()) -- 1
print(c1()) -- 2


递归:

local g = function (n)
    ...
    return g(n) -- err
end

这样会报错,递归时找不到g这个函数。需要先声明,local g,然后g=function(n)才可以找到。

函数最后一个动作是调用另外一个函数,叫做尾递归。lua对尾递归做了优化,不需要占用额外的栈空间。但是如果调用其他函数之后,后面做了一些没有意义的操作,则不视为尾递归,如结尾调用g(x)之后再return。

return g(x)+f(x)+a*b这样的表达式也是尾递归,lua会在调用前计算好表达式的值。


迭代器,泛型for

迭代器常用函数来描述,每次调用就返回集合的下一个元素。如何存储指针状态?用闭包。

function list_iter(t)
    local i=0
    local n = #t
    return function()
        i = i + 1
        if i<=n then return t[i] end
    end
end


上面的list_iter返回一个迭代器。闭包内部保存t,i,n,每次调用他都会返回list的下一个元素。

使用方法:

iter = list_iter(t)
while true do
    local e = iter()
    xxxx
    if e == nil then break end
end


或者

for e in list_iter(t)
    print(e)
end


泛型for更为复杂一点。不必要每次都用迭代器创建一个闭包。

for k,v in paris(t) do … end

in后面的表达式,返回三个值:迭代函数,状态常量,控制变量。

第一步先用表达式计算出上面三个值。

第二步将状态常量和控制变量传给迭代函数调用。

第三步将返回值付给变量列表(in前面的,控制变量也重新赋值)。

第四步返回的第一个值为nil,则结束。否则继续调用迭代函数(返回第二步)。

for var1,…,varn in explist do
    xxx 
end

等价于

do
    local _f,_s,_var = explist
    while true do
        local var1,…,varn = _f(_s,_var)
        _var = var1
        if _var == nil then break end
            …
        end
    end
end


回到顶部