美文网首页Lua点滴serverLua
Lua语言入门(二)

Lua语言入门(二)

作者: 小飞不会飞_ | 来源:发表于2016-09-21 17:14 被阅读85次

    函数

    24、函数
    格式:

    function fun_name(params)
    --body
    end
    

    调用方式:o.fun(x)o:fun(x),其中冒号调用方式会隐含将o作为函数第一个参数传入;

    参数:形参和实参数量可以不同,规则和多重赋值一致;

    多重返回值:只需在return时这样写 -- return a, b, c
    print可以接受不同数量的实参,多重返回值的函数可以直接作为其它函数的参数,也可以作为table的构造式 --> a = {f()};

    25、table.unpack:返回数组中所有值

    print(table.unpack({10, 20, 30}))
    
    local a = {10, 20, 30}
    print(table.unpack(a))
    
    local a = {}
    a[1] = 10;
    a[2] = 20;
    a[3] = 30;
    print(table.unpack(a))
    

    26、变长参数:lua的函数可以接受不同数量的实参

    function add(...)
     -- body
     local s = 0
     for i,v in ipairs{...} do  --注意这里是大括号
      s = s + v
     end
     return s
    end
    
    print(add(3,4, 10, 25, 12))    --54
    

    参数表中三个点(...)表示该函数可接受不同数量的实参。
    表达式(...)的行为类似一个具有多重返回值的函数。
    把第一个和第二个参数赋给a和b :local a, b = ...
    可以像访问数组一样去访问可变参数。
    select(p1, p2):p1为数字n,那么select返回它第n个可变实参;p1为‘#’select返回变长参数的总数。

    function fun( ... )
     -- body
     local len = select('#', ...) -- 获取长度
     local params = {...}
     for i=1,len do
      print(params[i])
     end
    end
    
    fun(3, 4, 10, 25, 12)
    

    27、具名实参:传递table

    28、深入理解函数
    在lua中,函数是一种第一类值,就是和其它传统类型一样可以存储到变量或table中,可以作为实参传递给其它函数,还可以作为其它函数的返回值。
    函数与所有其它值一样都是“匿名”的:函数定义有一下两种方法,表明fun只是一个持有函数的变量,而不是函数的名称。

    function fun( ... )
     -- body
    end
    
    fun = function( ... )
     -- body
     print('fun')
    end
    

    使用匿名函数:

    local tb = {
     {name = "grauna", level = "50"},
     {name = "lua", level = "10"},
     {name = "arraial", level = "30"}
    }
    
    table.sort( tb,
     function(a, b)  --匿名函数
      return (a.name < b.name)
     end)
    
    print(tb[1].name)
    print(tb[2].name)
    print(tb[3].name)
    

    table.sort用于对table中元素排序


    深入理解函数

    29、闭合函数:在函数内部定义的函数,能够通过建立一个闭合函数(closure),在外部函数已经执行完毕的情况下,还能访问到在外部函数中的局部变量。

    后来发现一个规律:所有定义在函数内部的函数,都不能直接在外部函数外部访问,只能通过外部函数把内部函数返回出来,这样在外部函数的外部才可以使用,这也就是闭包函数通俗的理解吧。例如下面代码中的 c1、c2

    function fun()
     -- body
     local i = 1
     print(i);
     return function()   --返回了闭包函数
      -- body
      i = i+1
      return i
     end
    end
    
    c1 = fun() --创建闭合函数 c1
    c2 = fun() --创建闭合函数 c2                  注意:这里进行的操作其实是执行了fun函数,但并没有执行匿名函数,而是把匿名函数赋值给c1、c2了,所以c1()、c2()其实执行里面匿名函数
    
    print(c1()) --也可以print(fun()())这样调用,print(fun())打印是fun函数里面的匿名函数的地址
    print(c1())
    print(c1())
    
    --输出 1 2 3 4
    

    在fun函数中匿名函数,仍能访问到fun作用域下的局部变量,i 对于匿名函数来讲被称作“非局部变量”。其中c1和c2是同一个函数创建的两个不同的closure,它们各自拥有局部变量的独立实例。

    30、非全局函数:函数可以存储在全局变量、局部变量、table字段中。只要将函数存到一个局部变量中,该函数只能在某个特定的作用域使用。
    定义:

    local a = function()
     -- body
    end
    
    local function a()
     -- body
    end
    

    31、尾调用消除
    尾调用:当 f 调用完 g 之后就再无其他事情可做了,这种情况下,当 g 返回时,执行控制权直接返回到调用 f 的那个点上。
    消除:在尾调用之后,程序不需要保存任何关于该函数的栈信息了,使得在进行尾调用时不耗费任何栈空间。

    function f()
     -- body
     print("f")
    
     g()  -- g()是函数f的最后调用
    end
    

    编译、执行、错误

    32、编译:区分解释型语言的主要特征不是能否去编译它们,而是在编译器是否是运行时库的一部分,是否有能力执行动态生成的代码。

    dofile:实际是调用loadfile,从文件加载lua代码,编译并运行,会引发错误

    loadfile:从文件加载lua代码,编译但不运行(编译成函数,作为匿名函数返回),不会引发错误,有错误时只是返回错误值
    源代码 foo.lua

    function foo(x)
     -- body
     print(x)
    end
    

    运行:

    f = loadfile("foo.lua") --只是返回了函数,但没有执行
    print(foo)    --nil
    f()               --定义foo函数
    foo("ok")    --ok
    

    load(低版本中是loadstring):从一个字符串读取代码,返回一个函数。(比直接定义函数写代码慢得多)

    i = 32
    local i = 0
    f = load("i = i+1;print(i)") --load总是在全局环境中编译的,所以这里访问到的i是全局变量i
    g = function() i = i+1;print(i) end
    
    f()
    g()
    
    --输出 33  1
    

    33、C代码:需要使用前先链接入应用程序
    loadlib函数加载指定的库,并将其链接入Lua:将C函数作为Lua函数返回

    local path = "/usr/local/lib/lua/5.1/socket.so"
    local f = package.loadlib(path, "luaopen_socket")
    

    34、错误(error):只要发生错误,Lua就会结束当前程序块并返回应用程序
    error

    if not n then
    error("invalid input") --显示抛出错误信息
    end
    

    assert(p1, p2):如果p1为true,就简单返回该参数,否者引发一个错误。p2是错误信息,可选

    35、错误处理和异常:pcall(protected call)来包装需要执行的代码,捕获函数执行中任何错误。

    function fun( ... )
     -- body
     print("fun")
     error("exception")
    end
    
    local status, err = pcall(fun)
    if status then
     --运行fun时没有发生错误
     print("not have error")
    else
     --错误处理代码
     print("have error")
     print(err) --只要错误消息是字符串,Lua就会附加一些错误发生位置的信息
    end
    

    相关文章

      网友评论

        本文标题:Lua语言入门(二)

        本文链接:https://www.haomeiwen.com/subject/jdsaettx.html