博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lua1 基础1
阅读量:7081 次
发布时间:2019-06-28

本文共 6580 字,大约阅读时间需要 21 分钟。

hot3.png



 注:本记录都摘录自: , 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.

    1. Boolean 类型只有两种值:false 和 true。 nil 和 false 都能导致条件为假;而另外所有的值都被当作真。

    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 当作一个拥有不定参数的匿名函数 (参见 )处理。 正是这样,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)      			        --> 6print(false or 5 and nil)				--> nilprint(false or 2+3 >= 4*1 and not 7^2)	--> falseprint(false or 2+3 >= 4*1 and not nil)	        --> trueprint(not nil)						--> trueprint(false or nil)					--> nil
  15. 常用却不在意的元方法:

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

    2. concat:字符串的连接操作符写作两个点 ('..')。 如果两个操作数都是字符串或都是数字,连接操作将以  中提到的规则把其转换为字符串。 否则,会取调用元方法 "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

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

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

简化函数定义:

  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 时才有。)

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

  1.      return (f(x))        -- 返回值被调整为一个     return 2 * f(x)     return x, f(x)       -- 最加若干返回值     f(x); return         -- 无返回值     return x or f(x)     -- 返回值被调整为一个

闭包:一个函数定义是一个可执行的表达式, 执行结果是一个类型为 function 的值。 当 Lua 预编译一个 chunk 的时候, chunk 作为一个函数,整个函数体也就被预编译了。 那么,无论何时 Lua 执行了函数定义, 这个函数本身就被实例化了(或者说是关闭了)。 这个函数的实例(或者说是closure(闭包)) 是表达式的最终值。 相同函数的不同实例有可能引用不同的外部局部变量, 也可能拥有不同的环境表。

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

我们先做如下定义,然后再来看一个例子:

  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

地方

转载于:https://my.oschina.net/u/2005342/blog/308175

你可能感兴趣的文章
SOAP--------Golang对接WebService服务实战
查看>>
7大维度看国外企业为啥选择gRPC打造高性能微服务?
查看>>
初创公司电商系统建立思考
查看>>
微服务框架Spring Cloud介绍 Part2: Spring Cloud与微服务
查看>>
zipfile
查看>>
很形象地展示了进程与线程的区别
查看>>
Hadoop中最不容错过的压缩知识
查看>>
个人比较喜欢用的链表查询
查看>>
MySql数据库操作
查看>>
台式电脑调整分区后盘符不见的数据怎样找回
查看>>
互联网创业的准备——数据库:硬盘iops、mysql
查看>>
最新Chalubo僵尸网络来袭,目标指向服务器和物联网设备
查看>>
Python(三)数据类型、操作符、输入输出、判断|循环语句
查看>>
区分零值指针,NULL指针,野指针
查看>>
个人银行账户小程序
查看>>
P2P技术原理及应用
查看>>
笔记RAID 和进程管理
查看>>
能否重拾Linux下Init 3的快感?
查看>>
Xcode8更新CocoaPods报错解决办法
查看>>
查看oracle数据库job及会话信息
查看>>