zoukankan      html  css  js  c++  java
  • lua 基础

    1. table:

      a = {}; a[x]不等价于a["x"],a["x"]等价于a.x,a[0]不等价于a["0"];

      #a取出的是table中连续数组的长度,从下标1开始;如果a[1] = 2; a[10000] = 3; #a是1;如果a[2] = 1; #a是0;

      a = {[1]="a", [2]="b", [3]="c", "d", "e"}; 遍历结果是:d e c。因为数组下标默认从1开始,并且d作为1下标的值,e作为2下标的值;

      a = {[1]="a", [2]="b", [3]="c",}和a = {[1]="a", [2]="b", [3]="c"; "one", "two", "three"}都是合法的;

    2. 类型转换:

      lua会自动进行类型转换:"10" + 1结果是11;"1.1"*"2"结果是2.2;"str" + 1运行出错;建议使用强制转换函数tonumber,tostring等;

    3. 算数操作符:

      ==:表示类型和值都相等为true;两个table只有在引用同一个table时才会相等;在比较字符串和数字大小的时候,lua会引发错误,例如"2" < 12;

      (a and b) or c 相当于 a ? b : c;

      x = x or v 相等于 if (x) x = x; else x = v;

    4. 赋值:

      a, b, c = 1, 2; 结果a=1,b=2,c=nil;

      a, b = 1, 2, 3; 结果a=1,b=2;

      a, b, c = 0; 结果是a=0,b=nil,c=nil,特别注意;

      x, y = y, x; 交换值,因为lua是先计算右边的表达式再进行复制;

      a, b = fun(); 函数返回多个结果;

    5. local:

      local语句声明一个局部变量,lua的局部作用域主要有函数体和程序块(do-end then-else then-elseif then-end);

      尽可能使用局部变量的原因:

        (1)避免全局变量污染;

        (2)局部变量的访问速度更快,可以优化性能;

        (3)局部变量会在作用域结束的时候被垃圾回收器回收,减少不必要的内存浪费;

      local foo = foo;暂存全局变量中的值,防止foo被修改,还可以加速对foo的访问;

    6. for:

      for i = 1, 5, 1 then do; i是局部变量,for循环完成之后会被销毁;

      for i, v in ipairs(a) do;迭代数组元素;

      for k, v in pairs(a) do;迭代所有元素;

    7. 函数:

      lua函数可以返回多个值的情况:

        (1)x, y = foo(); x, y, z = 10, foo(); 如果函数调用是最后一个表达式,函数会返回尽可能多的返回值;

        (2)x, y = foo(), 2; 如果函数调用是第一个表达式,函数只返回一个返回值;

        (3)print(foo().."x"); 如果函数调用出现在表达式中,函数只返回一个返回值;

        (4)f(g()); g将返回值个数调整和f的参数个数一致;

        (5)return f(); 将返回f的所有返回值;

        (6)return (f()); ()表达式将强制只返回一个返回值;

        (7)t = {f()}; 可以使用数组包含所有返回值;

    8. 变成参数:

      访问变成参数...的两种方式:

        (1)使用{...},想数组一样遍历其中的元素;

        (2)select("#", ...)获取长度,select(i, ...)获取i下表的元素;

    9. 闭包的使用场景:

      单列模式,隐蔽数据;

      例如:

    local _a = 1;
    local _b = 2;
    local _c = 3;
    
    local _instance = {};
    _instance.setvalue = function (a, b, c)
        _a = a;
        _b = b;
        _c = c;
    end
    _instance.print = function()
        print("instance value:", _a, _b, _c);
    end
    
    local module1 = {};
    module1.getInstance = function()
        return _instance;
    end
    
    return module1;

      回调函数;

      例如:

    function digitButton(digit)
        return Button{
            label = tostring(digit);
            action = function()
                print(digit)
            end
        }
    end

      重新定义某些函数,并可以通过闭包保持对旧函数的访问;  

      例如:

    do
        local oldsin = math.sin
        math.sin = function(x)
            return oldsin(x * math.pi / 180)
        end
    end

    10. 函数定义:

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

      上诉递归函数的定义会出现错误,解释器在解释fact(n-1)的时候,会找不到定义,因为fact还没有完成定义。需要修改成:

      local fact

      fact = function(n)

      ...

      end

      或者:

      local function fact(n)

      ...

      end

    11. 尾调用:

      只有在函数调用的最有一个语句是:return <func>(<args>); 才算是尾调用。

      以下情况都不算尾调用:

        function f() g() end; 因为还要处理g()的临时返回值;

        function f() return g() + 1; 还要做一次加法计算;

        function f() return (g()); 还要调整返回值;

      使用尾调用的好处是:没有函数调用栈的开销;

    12. 编译:

      loadfile:编译一个lua文件,返回一个可执行的函数,调用函数就等于执行编译好的lua代码。

      dofile:编译lua文件,并且会执行,而去会处理错误,代码相当于:

        function dofile(filename)

          local f = assert(loadfile(filename))

          return f()

        end

      loadfile会返回错误,但是不会处理错误,所有需要用assert;

      dofile会在每次调用都重新编译,因此,如果需要一次编译,多次运行,则使用loadfile;

      例子1(编译时的运行环境):

      module1.lua

        gi = gi + 1;

        print(gi);

      test1.lua

        local gi = 4;

        local f = assert(loadfile(module1.lua));

        f(); // 错误, 因为在编译的时候,没有找到全局变量gi的定义,如果将test1中的gi的local去掉,则可以正常运行。

          // 说明loadfile的编译是在当前运行环境中进行编译,而不是在独立的运行环境中进行编译

        print(gi); // 4

      test2.lua

        gi = 4;

        local f = assert(loadfile(module1.lua));

        f(); // 5 调用f就像调用普通lua函数一样,所以gi会被递增

        f(); // 6

      test3.lua

        gi = 4;

        dofile(module1.lua); // 5 每次都会重新编译,所以两次调用结果一样

        dofile(module1.lua); // 5

      例子2:

      module1.lua

        function foo()

          print("foo");

        end

      test1.lua

        local f = assert(loadfile(module1.lua));

        foo(); // 错误,lua中函数的定义其实是一种赋值,是在运行时确定的,因此编译时无法找到foo的定义;

        f();

        foo(); // 打印foo,在运行f()后,定义就完成了;

      上面例子中,foo是全局的函数变量,如果改为局部变量local foo = funtion() print("foo") end,在test1.lua中将访问不了foo,即时是在f()之后;

    13. 错误:

      assert(bool, message): lua中的断言可以中断程序的执行并打印错误堆栈;

      error:抛出一个lua错误,可以传入任意类型,包括字符串,数字或者table来标示错误信息;

      pcall:pcall称为保护调用,通常用来捕获异常和处理异常。pcall在调用一个函数的时候,如果函数正常运行,返回true和函数返回值;如果出现错误,返回false和错误消息;

      xpcall:同样也是保护调用,和pcall不同的是,xpcall的第二个参数可以提供一个异常处理函数,让用户可以自己处理异常情况。正常运行时候和pcall的机制一样,当出现异常后,返回fasle和nil,并且会调用异常处理函数;

      例子:

      function foo()

        if (s == 1) then return 5;

        else error("foo error"); end

      end

      s = 1;

      local status, data = pcall(foo); // status = true, data = 5

      s = 2;

      local status, error = pcall(foo); // status = false, error = "foo error"

      assert和error都可以产生异常,但是error可以自定义错误的信息,更加灵活;

      例子:

      local status, data = xpcall(foo, function()

        print(debug.traceback()); // 打印异常发生时的调用栈信息 

      end);

  • 相关阅读:
    开发导致的内存泄露问题,运维小伙伴儿这样排查不背锅
    JVM垃圾回收器、内存分配与回收策略
    笔试编程(二) | 7种常见的排序算法解析(附实现代码)
    HBase高级特性、rowkey设计以及热点问题处理
    Geotools创建Feature的两种方式
    geotools实现追加数据到数据库
    Java连接mysql数据库经典代码
    leaflet加载高德地图和Geoserver的WMS服务
    geotools学习之连接数据库并获取数据
    LeaFlet中切片图层使用自定义坐标系
  • 原文地址:https://www.cnblogs.com/iRidescent-ZONE/p/5630735.html
Copyright © 2011-2022 走看看