程序员

lua学习笔记

2020-07-01  本文已影响0人  yellowone

Lua学习笔记

为什么要学习lua

最重要的当然是工作原因,最近有个项目是相关于游戏服务器的,而用的框架是skynet,用的语言是lua。

然后lua对nginx和redis也有用处,学了也不吃亏,就写这篇东西做一个总结。

看的文档是这个

云风大神写的。

简介:

基本概念

值与类型

环境和局部变量

错误处理

元表及元方法

垃圾收集

协程

语言定义

词法约定

a = [[alo
     123"]]
     a = [==[
     alo
     123"]==]

变量

语句

控制结构

if, while, and repeat 这些控制结构符合通常的意义,而且也有类似的语法:

    stat ::= while exp do block end
    stat ::= repeat block until exp
    stat ::= if exp then block {elseif exp then block} [else block] end

还有goto,break,return。

for有两种形式:一种是数字形式,另一种是通用形式。

数字形式的 for 循环,通过一个数学运算不断地运行内部的代码块。 下面是它的语法:

    stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end

通用形式的 for 通过一个叫作 迭代器 的函数工作。 每次迭代,迭代器函数都会被调用以产生一个新的值, 当这个值为 nil 时,循环停止。 通用形式的 for 循环的语法如下:

    stat ::= for namelist in explist do block end
    namelist ::= Name {‘,’ Name}

表达式

Lua 中有这些基本表达式:

    exp ::= prefixexp
    exp ::= nil | false | true
    exp ::= Numeral
    exp ::= LiteralString
    exp ::= functiondef
    exp ::= tableconstructor
    exp ::= ‘...’
    exp ::= exp binop exp
    exp ::= unop exp
    prefixexp ::= var | functioncall | ‘(’ exp ‘)’

函数调用和可变参数表达式都可以放在多重返回值中。值的个数不一致时,通过补nil和抛弃做调整。需要注意的是被括号括起来的表达式永远被当作一个值。 所以, (f(x,y,z)) 即使 f 返回多个值, 这个表达式永远是一个单一值。 ((f(x,y,z)) 的值是 f 返回的第一个值。 如果 f 不返回值的话,那么它的值就是 nil 。)

这里有一些例子:

     f()                -- 调整为 0 个结果
     g(f(), x)          -- f() 会被调整为一个结果
     g(x, f())          -- g 收到 x 以及 f() 返回的所有结果
     a,b,c = f(), x     -- f() 被调整为 1 个结果 (c 收到 nil)
     a,b = ...          -- a 收到可变参数列表的第一个参数,
                        -- b 收到第二个参数(如果可变参数列表中
                        -- 没有实际的参数,a 和 b 都会收到 nil)

     a,b,c = x, f()     -- f() 被调整为 2 个结果
     a,b,c = f()        -- f() 被调整为 3 个结果
     return f()         -- 返回 f() 的所有返回结果
     return ...         -- 返回从可变参数列表中接收到的所有参数parameters
     return x,y,f()     -- 返回 x, y, 以及 f() 的所有返回值
     {f()}              -- 用 f() 的所有返回值创建一个列表
     {...}              -- 用可变参数中的所有值创建一个列表
     {f(), nil}         -- f() 被调整为一个结果

操作符

Lua 支持下列数学运算操作符:

除了乘方和浮点除法运算, 数学运算按如下方式工作: 如果两个操作数都是整数, 该操作以整数方式操作且结果也将是一个整数。 否则,当两个操作数都是数字或可以被转换为数字的字符串 (参见 §3.4.3)时, 操作数会被转换成两个浮点数, 操作按通常的浮点规则(一般遵循 IEEE 754 标准) 来进行,结果也是一个浮点数。

乘方和浮点除法 (/) 总是把操作数转换成浮点数进行,其结果总是浮点数。 乘方使用 ISO C 函数 pow, 因此它也可以接受非整数的指数。

Lua 支持下列位操作符:

Lua 对一些类型和值的内部表示会在运行时做一些数学转换。 位操作总是将浮点操作数转换成整数。 乘方和浮点除法总是将整数转换为浮点数。 其它数学操作若针对混合操作数 (整数和浮点数)将把整数转换为浮点数; 这一点被称为 通常规则

当操作需要数字时,Lua 还会把字符串转换为数字。

等于操作不会将字符串转换为数字,反之亦然。 即,"0"==0 结果为 false

所有的逻辑操作符把 falsenil 都作为假, 而其它的一切都当作真。

逻辑操作符

Lua 中的逻辑操作符有 andor,以及 not

取反操作 not 总是返回 falsetrue 中的一个。

     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

字符串连接

Lua 中字符串的连接操作符写作两个点('..')

取长度操作符

取长度操作符写作一元前置符 #。 字符串的长度是它的字节数(就是以一个字符一个字节计算的字符串长度)。

表构建

 a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

等价于

     do
       local t = {}
       t[f(1)] = g
       t[1] = "x"         -- 1st exp
       t[2] = "y"         -- 2nd exp
       t.x = 1            -- t["x"] = 1
       t[3] = f(x)        -- 3rd exp
       t[30] = 23
       t[4] = 45          -- 4th exp
       a = t
     end

构造子中赋值的次序未定义。 (次序问题只会对那些键重复时的情况有影响。)

函数定义

该语句

     function f () body end

被转译成

     f = function () body end

该语句

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

被转译成

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

该语句

     local function f () body end

被转译成

     local f; f = function () body end

而不是

     local f = function () body end

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

可见性规则

     x = 10                -- 全局变量
     do                    -- 新的语句块
       local x = x         -- 新的一个 'x', 它的值现在是 10
       print(x)            --> 10
       x = x+1
       do                  -- 另一个语句块
         local x = x+1     -- 又一个 'x'
         print(x)          --> 12
       end
       print(x)            --> 11
     end
     print(x)              --> 10 (取到的是全局的那一个)

注意,每次执行到一个 local 语句都会定义出一个新的局部变量。 看看这样一个例子:

     a = {}
     local x = 20
     for i=1,10 do
       local y = 0
       a[i] = function () y=y+1; return x+y end
     end

这个循环创建了十个闭包(这指十个匿名函数的实例)。 这些闭包中的每一个都使用了不同的 y 变量, 而它们又共享了同一份 x

编程接口

这个部分描述了 Lua 的 C API , 也就是宿主程序跟 Lua 通讯用的一组 C 函数。 所有的 API 函数按相关的类型以及常量都声明在头文件 lua.h 中。

C 库中所有的 Lua API 函数都不去检查参数是否相容及有效。 然而,你可以在编译 Lua 时加上打开一个宏开关 LUA_USE_APICHECK 来改变这个行为。

Lua 使用一个 虚拟栈 来和 C 互传值。 栈上的的每个元素都是一个 Lua 值 (nil,数字,字符串,等等)。每次调用的栈都是全新的。

栈大小

当你使用 Lua API 时, 就有责任保证做恰当的调用。 特别需要注意的是, 你有责任控制不要堆栈溢出。 你可以使用 lua_checkstack 这个函数来扩大可用堆栈的尺寸。

再之后就是各种自带函数的用法了,遇到再查。

上一篇下一篇

猜你喜欢

热点阅读