lua笔记

作者: 黒可乐 | 来源:发表于2017-07-18 14:35 被阅读0次

    写在前面,有一点乱。

    8种数据 nil, boolean, number, string, function, userdata, thread, and table.


    table表的索引不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。

    local 局部变量 有效区域在声明开始到下一个end之间。
    默认情况下变量总是认为全局变量,全局变量不需要声明,给一个变量赋值后即创建了这个全局变量。如果不赋值就访问这个变量不会出错,得到的结果是nil。

    a, b, c = 0
    print(a,b,c) --> 0 nil nil
    这个声明变量是只对a做了声明,其他的没有。


    如果你想删除一个全局变量,只需要将变量赋值为nil。

    字符串相加..
    如果是+符号操作它会强制转换为number,再加

    循环语句:

    这里默认的步长为1
    for index=1,4 do
    print("index=",index)
    end

    这里可以设置步长,第三个参数即为步长,正数即为加,负数即为递减。
    for index=1,4,2 do
    print("index=",index)
    end

    泛型循环类似foreach
    tab1 = { key1 = "val1", key2 = "val2", "val3" }
    for k, v in pairs(tab1) do
    print(k .. " - " .. v)
    end

    myValue=17
    if myValue<6 then
    print("s")
    elseif myValue>20 then
    print("aa")
    end

    while myValue <20 do
    print("sssa")
    myValue=myValue+1
    end

    repeat
    print("repeat")
    myValue=myValue+1
    until myValue<20

    循环中有break打断,但是没有continue。

    注释:
    单行注释:

    --
    

    多行注释:

    --[[
      多行注释
    
     --]]
    

    判断:
    if false or nil then
    print("至少有一个是 true")
    else
    print("false 和 nil 都为 false!")
    end

    函数:

     optional_function_scope function function_name(argument1, argument2, argument3..., argumentn)
     function_body
      return result_params_comma_separated
    end
    
    • optional_function_scope:*
      该参数是可选的制定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。
      function_name:
      指定函数名称。
      argument1, argument2, argument3..., argumentn:
      函数参数,多个参数以逗号隔开,函数也可以不带参数。
      function_body:
      函数体,函数中需要执行的代码语句块。
      result_params_comma_separated:
      函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。

    可以返回多个返回值,也可以有不定参数,不定参数括号里面写...三个点,相当于是这个是传入的一个table,也就是说分别把table中的数据添加进去。

    模块与包:
    这个模块有点像封装库,在使用时只需要导入即可。模块是用table来组成的,这个table就有一些像类。在定义这个模块的变量或者函数时,需要在变量名或函数名前面加上这个table的名字,列如table.mString、table.Print()。
    导入这个模块使用require即可,有点像include的写法。

    require "模块名"
    require "table"
    print(table.mString)
    table.Print()
    

    这里的require的加载机制是需要设置一个LUA_PATH环境变量,这里的模块名就是在这个路径下的一个表,也可以再延续下路径。这里的require相当于就是把一个lua文件直接复制到相应的文件中去。

    元表:
    设置元表:

    mytable = {}                          -- 普通表 
    mymetatable = {}                      -- 元表
    setmetatable(mytable,mymetatable)     -- 把 mymetatable 设为 mytable 的元表 
    

    也可以写成一行:

    mytable = setmetatable({},{})
    

    这个是一个操作table的东西,,比如说当访问到某一个index的时table表中没有这个index,就去元表使用的__index元方法中找这个index。当使用table.newkey时,table中没有newkey这个key值就会调用__newindex这个元方法,所以这里就不会对table中的newkey这个可以对应的value赋值。这里说的有点绕。

    操作符相对应的元方法

    还有就是__call:是在Lua调用一个值时调用,换句话说就是把table作为一个方法直接调用。
    __tostring方法:更改表的输出行为调用。

    协同程序:
    这个与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其他的协同程序共享全局变量和其他大部分东西。
    线程和协同程序区别
    线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。
    在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。
    协同程序有点类似同步的多线程,在等待同一个线程锁的几个线程有点类似协同。
    基本语法

    值得注意的是coroutine.yield是把协同挂起,在挂起后再次调用coroutine.resume重启协同,是接着coroutine方法中上一个coroutine.yield语句的下一句开始执行。
    第一次传入的值时这个方法开头写function(参数)传入的参数,在后面需要传入的新的参数是在coroutine.yield前面声明变量。

      local a,b = coroutine.yield()
    

    这里就可以传入两个值。
    在整个协同方法执行完后,再调用coroutine.resume方法输出的是:cannot resume dead coroutine,可以理解为一个协同程序是一次性的。
    实例:

    function foo (a)
        print("foo 函数输出", a)
        return coroutine.yield(2 * a) -- 返回  2*a 的值
    end
    
    co = coroutine.create(function (a , b)
        print("第一次协同程序执行输出", a, b) -- co-body 1 10
        local r = foo(a + 1)
     
        print("第二次协同程序执行输出", r)
        local r, s = coroutine.yield(a + b, a - b)  -- a,b的值为第一次调用协同程序时传入
     
        print("第三次协同程序执行输出", r, s)
        return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入
    end)
        
    print("main", coroutine.resume(co, 1, 10)) -- true, 4
    print("--分割线----")
    print("main", coroutine.resume(co, "r")) -- true 11 -9
    print("---分割线---")
    print("main", coroutine.resume(co, "x", "y")) -- true 10 end
    print("---分割线---")
    print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
    print("---分割线---")
    

    输出结果:

    第一次协同程序执行输出 1   10
    foo 函数输出    2
    main    true    4
    --分割线----
    第二次协同程序执行输出 r
    main    true    11  -9
    ---分割线---
    第三次协同程序执行输出 x   y
    main    true    10  结束协同程序
    ---分割线---
    main    false   cannot resume dead coroutine
    ---分割线---
    

    Lua 文件 I/O:

    file = io.open (文件名,操作模式)
    

    操作模式:

    操作模式

    file:close(),file:write("内容"),file:read("模式"),这里的模式可以不填。

    file:read填入的模式

    冒号与点的区别:
    lua中使用table来作为对象的编写,我们可以使用table.property的这个方式来访问table中的属性。当然也可以使用点或者冒号来调用table中的方法。
    冒号这里在编写方法或调用方法时,默认传入一个自身table进。而点则没有。由此看来点的使用方式更加的灵活一些。如果说一个table中定义好了一个方法method,使用冒号写的,这里把这个table赋值给另一个newtable,然后newtable调用method,这里如果其中使用了self的话,这里是不会有效果的,因为newtable中的method传入的是newtable了而不是table。
    举个例子:

    c = {a = 1, b = 2}
    
    c.foo = function(c) print(c.a,c.b) end
    
    d = {}
    
    d.foo2 = c.foo
    
    d:foo2()
    

    输出为:nil nil

    解释下上面的代码:

    首先创建一个table,然后定义一个函数foo,这个函数访问了table中的a和b两个变量

    然后创建了另一个table,b

    在b中定义一个变量foo2,赋值为c这个table中的foo函数

    然后调用d这个table中的foo2函数,输出为nil nil

    因为d是两个点调用的foo2,那么会自动吧d本身传入函数的第一个参数,那么函数的运行就是这样的:

    function (d)
    
      print(d.a,d.b)
    
    end
    

    d这个table没有定义a和b两个变量,输入当然就是nil

    像这种情况就只能一个点调用,显示的传入c这个table

    d:foo2()改为d.foo2(c) 这样就可以了

    输出1 2

    上面的例子还可以这么写:

    c = {a=1,b=2}
    function c:foo()
      print(self.a,self.b)
    end
    
    d = {}
    d.foo2 = c.foo
    
    d.foo2(c)

    相关文章

      网友评论

          本文标题:lua笔记

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