lua1 基础1


html

 注:本记录都摘录自:http://manual.luaer.cn/ , lua在线手册 。1-2.5部分。程序员


  1.  相似 C 的转义符: '\a' (响铃), '\b' (退格), '\f' (表单), '\n' (换行), '\r' (回车), '\t' (横向制表), '\v' (纵向制表), '\\' (反斜杠), '\"' (双引号), 以及 '\'' (单引号)。 数组

  2. 反斜杠加数字的形式 \ddd 来描述一个字符,注意,若是须要在这种描述方法后接一个是数字的字符, 那么反斜杠后必须写满三个数字。闭包

    1.  下面五种方式描述了彻底相同的字符串:函数

      1.      a = 'alo\n123"'
             a = "alo\n123\""
             a = '\97lo\10\04923"'
             a = [[alo
             123"]]
             a = [==[
             alo
             123"]==]
  3. Lua 中有八种基本类型: nilbooleannumberstringfunction, userdatathread, and table.lua

    1. Boolean 类型只有两种值:false 和 true。 nil 和 false 都能致使条件为假;而另外全部的值都被看成真。spa

    2. Number 表示实数(双精度浮点数)。操作系统

    3. userdata 类型用来将任意 C 数据保存在 Lua 变量中。 这个类型至关于一块原生的内存,除了赋值和相同性判断,Lua 没有为之预约义任何操做。 然而,经过使用 metatable (元表) ,程序员能够为 userdata 自定义一组操做。 userdata 不能在 Lua 中建立出来,也不能在 Lua 中修改。这样的操做只能经过 C API。 这一点保证了宿主程序彻底掌管其中的数据。线程

    4. thread 类型用来区别独立的执行线程,它被用来实现 coroutine (协同例程)。 不要把 Lua 线程跟操做系统的线程搞混。 Lua 能够在全部的系统上提供对 coroutine 的支持,即便系统并不支持线程。调试

    5. table 类型实现了一个关联数组。语言自己采用一种语法糖,支持以 a.name 的形式表示 a["name"]。

    6.  特别的,由于函数自己也是值,因此 table 的域中也能够放函数。 这样 table 中就能够有一些 methods 了。

    7. table, function ,thread ,和 (full) userdata 这些类型的值是所谓的对象: 变量自己并不会真正的存放它们的值,而只是放了一个对对象的引用。 赋值,参数传递,函数返回,都是对这些对象的引用进行操做; 这些操做不会作暗地里作任何性质的拷贝。

  4. Boolean 类型只有两种值:false 和 true。 nil 和 false 都能致使条件为假;而另外全部的值都被看成真。

  5. Number 表示实数(双精度浮点数)。

  6. Lua 提供运行时字符串到数字的自动转换。 

  7. 全局变量,局部变量,还有 table 的域。

  8.  chunk :Lua 的一个执行单元被称做 chunk。 一个 chunk 就是一串语句段,它们会被循序的执行。 每一个语句段能够以一个分号结束。lua 把一个 chunk 看成一个拥有不定参数的匿名函数 (参见 §2.5.9)处理。 正是这样,chunk 内能够定义局部变量,接收参数,而且返回值。

  9. 赋值:赋值段首先会作运算完全部的表达式,而后仅仅作赋值操做。 所以,下面这段代码

    1.  i = 3
       i, a[i] = i+1, 20
    2. 会把 a[3] 设置为 20,而不会影响到 a[4] 。 这是由于 a[i] 中的 i 在被赋值为 4 以前就被拿出来了(那时是 3 )。 简单说 ,这样一行

    3. x, y = y, x
    4. 能够用来交换 x 和 y 中的值。

  10. for 和 while:

    1. for v = e1, e2, e3 do block end
    2. 用while表达:

    3.     do
             local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
             if not (var and limit and step) then error() end
             while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
               local v = var
               block
               var = var + step
             end
           end
    4. 注意:有个问题,for i=3,2,0 do print(i) end, 会进入死循环。

  11. 可变参数:函数调用和可变参数表达式均可以放在多重返回值中。 若是表达式做为一个独立语句段出现 (这只能是一个函数调用), 它们的返回列表将被对齐到零个元素,也就是忽略全部返回值。 若是表达式用于表达式列表的最后(或者是惟一)的元素, 就不会有任何的对齐操做(除非函数调用用括号括起来)。 在任何其它的状况下,Lua 将把表达式结果当作单一元素, 忽略除第一个以外的任何值。被括号括起来的表达式永远被看成一个值。因此, (f(x,y,z)) 即便 f 返回多个值,这个表达式永远是一个单一值。 ((f(x,y,z)) 的值是 f 返回的第一个值。若是 f 不返回值的话,那么它的值就是 nil 。)

    1.      f()                    -- 调整到 0 个结果
           g(f(), x)              -- f() 被调整到一个结果
           g(x, f())              -- g 被传入 x 加上全部 f() 的返回值
           a,b,c = f(), x         -- f() 被调整到一个结果 ( c 在这里被赋为 nil )
           a,b = ...              -- a 被赋值为可变参数中的第一个,
                                      -- b 被赋值为第二个 (若是可变参数中并无对应的值,
      						-- 这里 a 和 b 都有可能被赋为 nil)
           
           a,b,c = x, f()         -- f() 被调整为两个结果
           a,b,c = f()            -- f() 被调整为三个结果
           return f()             -- 返回 f() 返回的全部结果
           return ...             -- 返回全部从可变参数中接收来的值
           return x,y,f()         -- 返回 x, y, 以及全部 f() 的返回值
           {f()}                    -- 用 f() 的全部返回值建立一个列表
           {...}                      -- 用可变参数中的全部值建立一个列表
           {f(), nil}                 -- f() 被调整为一个结果
  12. 比较操做符:等于操做 (==) 首先比较操做数的类型。 若是类型不一样,结果就是 false。 不然,继续比较。 数字和字符串都用常规的方式比较。 对象 (table ,userdata ,thread ,以及函数)以引用的形式比较: 两个对象只有在它们指向同一个东西时才认为相等。 每次你建立一个新对象(一个 table 或是 userdata ,thread 函数), 它们都各不相同,即不一样于上次建立的东西。

  13. andor, 以及 not:and要找一个假的,or要找一个真的,找到就返回;到最后也找不到就返回最后的元素。

    1.      10 or 20            --> 10
           10 or error()       --> 10
           nil or "a"          --> "a"
           nil and 10          --> nil
           false and error()   --> false
           false and nil       --> false
           false or nil        --> nil
           10 and 20           --> 20
  14. 操做符的优先级:写在下表中,从低到高优先级排序:

    1.      or
           and
           <     >     <=    >=    ~=    ==
           ..
           +     -
           *     /     %
           not   #     - (unary)
           ^
    2. 一般,能够用括号来改变运算次序。 链接操做符 ('..') 和幂操做 ('^') 是从右至左的。 其它全部的操做都是从左至右。下面是一些例子:

    3. print(false or 5 and 6)      			        --> 6
      print(false or 5 and nil)				--> nil
      print(false or 2+3 >= 4*1 and not 7^2)	--> false
      print(false or 2+3 >= 4*1 and not nil)	        --> true
      print(not nil)						--> true
      print(false or nil)					--> nil
  15. 经常使用却不在乎的元方法:

    1. "lt" 或是 "le":大小比较操做以如下方式进行。 若是参数都是数字,那么就直接作数字比较。 不然,若是参数都是字符串,就用字符串比较的方式进行。 再则,Lua 就试着调用 "lt" 或是 "le" 元方法 。

    2. concat:字符串的链接操做符写做两个点 ('..')。 若是两个操做数都是字符串或都是数字,链接操做将以 &sect;2.2.1 中提到的规则把其转换为字符串。 不然,会取调用元方法 "concat"。

  16. 取长度操做符:写做一元操做 #。 字符串的长度是它的字节数(就是以一个字符一个字节计算的字符串长度)。

    table t 的长度被定义成一个整数下标 n 。 它知足 t[n] 不是 nil 而 t[n+1] 为 nil; 此外,若是 t[1] 为 nil ,n 就多是零。 对于常规的数组,里面从 1 到 n 放着一些非空的值的时候, 它的长度就精确的为 n,即最后一个值的下标。 若是数组有一个“空洞” (就是说,nil 值被夹在非空值之间), 那么 #t 多是任何一个是 nil 值的位置的下标 (就是说,任何一个 nil 值都有可能被当成数组的结束)。

  17. 语法糖:

    1. 表:a.name 的形式表示 a["name"];

    2. 函数: v:name(args) 这个样子,被解释成 v.name(v,args), 这里 v 只会被求值一次。

    3. 函数:调用形式 f{fields} 是一种语法糖用于表示 f({fields}); 这里指参数列表是一个单一的新建立出来的列表;

    4. 函数:形式 f'string' (或是 f"string" 亦或是 f[[string]]) 也是一种语法糖,用于表示 f('string'); 这里指参数列表是一个单独的字符串。

    5. 冒号语法能够用来定义方法, 就是说,函数能够有一个隐式的形参 self。 所以,以下写法:

          function t.a.b.c:f (params) body end

    6.     是这样一种写法的语法糖:

          t.a.b.c.f = function (self, params) body end

    7. 简化函数定义:

      1. 这样的写法:

         function f () body end

        被转换成

        f = function () body end

      2. 这样的写法:

        function t.a.b.c.f () body end

        被转换成

         t.a.b.c.f = function () body end

      3. 这样的写法:

        local function f () body end

         被转换成

         local f; f = function () body end

        注意,并非转换成

         local f = function () body end

        (这个差异只在函数体内须要引用 f 时才有。)



  18. 尾调用:调用形式:return functioncall 将触发一个尾调用。 Lua 实现了适当的尾部调用(或是适当的尾递归): 在尾调用中, 被调用的函数重用调用它的函数的堆栈项。 所以,对于程序执行的嵌套尾调用的层数是没有限制的。 然而,尾调用将删除调用它的函数的任何调试信息。 注意,尾调用只发生在特定的语法下, 这时, return 只有单一函数调用做为参数; 这种语法使得调用函数的结果能够精确返回。 所以,下面这些例子都不是尾调用:

    1.      return (f(x))        -- 返回值被调整为一个
           return 2 * f(x)
           return x, f(x)       -- 最加若干返回值
           f(x); return         -- 无返回值
           return x or f(x)     -- 返回值被调整为一个
  19. 闭包:一个函数定义是一个可执行的表达式, 执行结果是一个类型为 function 的值。 当 Lua 预编译一个 chunk 的时候, chunk 做为一个函数,整个函数体也就被预编译了。 那么,不管什么时候 Lua 执行了函数定义, 这个函数自己就被实例化了(或者说是关闭了)。 这个函数的实例(或者说是closure(闭包)) 是表达式的最终值。 相同函数的不一样实例有可能引用不一样的外部局部变量, 也可能拥有不一样的环境表。

  20. 形参,实参当一个函数被调用, 若是函数没有被定义为接收不定长参数,即在形参列表的末尾注明三个点 ('...'), 那么实参列表就会被调整到形参列表的长度, 变长参数函数不会调整实参列表; 取而代之的是,它将把全部额外的参数放在一块儿经过变长参数表达式传递给函数, 其写法依旧是三个点。 这个表达式的值是一串实参值的列表,看起来就跟一个能够返回多个结果的函数同样。 若是一个变长参数表达式放在另外一个表达式中使用,或是放在另外一串表达式的中间, 那么它的返回值就会被调整为单个值。 若这个表达式放在了一系列表达式的最后一个,就不会作调整了(除非用括号给括了起来)。

    咱们先作以下定义,而后再来看一个例子:

    1.      function f(a, b) end
           function g(a, b, ...) end
           function r() return 1,2,3 end

    下面看看实参到形参数以及可变长参数的映射关系:

    1.      CALL            PARAMETERS
           
           f(3)             a=3, b=nil
           f(3, 4)          a=3, b=4
           f(3, 4, 5)       a=3, b=4
           f(r(), 10)       a=1, b=10
           f(r())           a=1, b=2
           
           g(3)             a=3, b=nil, ... -->  (nothing)
           g(3, 4)          a=3, b=4,   ... -->  (nothing)
           g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
           g(5, r())        a=5, b=1,   ... -->  2  3
  21. 地方

相关文章
相关标签/搜索