Lua Manual 阅读笔记

  • 关键字:

    and break do else elseif end false for function if in local
    nil not or repeat return then true until while
    
  • Lua 中约定: 以下划线开头, 后接大写字母的为保留的全局变量. 例如 _VERSION

    > print(_VERSION)
    Lua 5.1
    
  • tokens:

    + - * / % ^ # == ~= <= >= < > =
    (  ) {  } [  ] ; : , . .. ...
    
  • 字符串可以以单引号或者双引号包围,中间可以包含c风格的转义字符串如 \t 等.

    • \a 响铃
    • \b 空格
    • \f form feed
    • \n 新的一行
    • \r 回车
    • \t 横向tab
    • \v 纵向tab
    • \\ \本身
    • \" 双引号本身
    • \' 单引号本身
    • \ 加 回车代表字符串里新的一行
  • 不转义字符可以用 [[ 的两个 [ 中间加上n个 = 来表示, 0个就是0级, n个就是 n级. 如果开括号后直接跟一个换行符, 则忽略这个换行符:

    > print('hello\n123')
    hello
    123
    > print([[hello
    >> 123]])
    hello
    123
    > print([[
    >> hello
    >> 123]])
    hello
    123
    
  • 字符串也可以用 \ 加上其ascii值来表示, 十进制,最多三位. 如 \97

  • -- 开头的是注释, 后面可以接双括号, 不过我还是喜欢每行 -- 因为vim帮我干了.

  • lua中的值有八种类型:

    • nil
    • boolean
    • number
    • string
    • function
    • userdata 用来存储裸的内存块,只能通过c API来操作,不能在lua中直接操作
    • thread 协程中的”线程”的概念,相当于Golang中的 G
    • table 是lua中的一个数据结构,既可以当数组用,又可以当哈希表用,还有 a.name 语法糖,相当于 a["name"]

type 函数返回数据的类型:

> print(type(1))
number
> print(type("hello"))
string
  • lua会在操作字符串和数字的时候自动进行类型转换,例如:

    > print(1 + "2")
    3
    

坑啊…和js一样…我很讨厌这种特性.

  • Lua有三种变量

    • 全局变量
    • 本地变量
    • table项(table fields)

var ::= Name 的形式赋值给变量, 默认全局变量, 除非加了 local 关键字, 本地变量可以被其作用域内的函数访问到. 第一次赋值前, 变量的默认值为 nil. 全局变量存储在 _env 里.

默认全局变量,又是一个坑.

  • 赋值, 赋值的时候, 如果右边比左边长, 则多余的值会被丢掉. 相反, 则用nil填充. 赋值语句首先计算出所有变量,然后才进行赋值,例如:

    i = 3
    i, a[i] = i+1, 20
    

执行完之后, a[3] 的值是20, a[4] 不受影响.

  • falsenil 是false,其他的都是true, 所以0和空字符串也是true.

  • for有两种形式, 一种像c:

    local i = 0
    
    for i = 0, 10, 2 do
    print(i)
    end
    
    $ luajit test.lua 
    0
    2
    4
    6
    8
    10
    

只能用来做算术循环.

另一种像 Python:

local names = {"hello", "world"}

for k, v in ipairs(names) do
    print(k, v)
end
$ luajit test.lua 
1	hello
2	world
  • 函数和变长参数都可以产生多值. 如果作为表达式, 那么结果会被忽略, 例如函数 调用 f() 那么其结果会被忽略. 如果作为表达式的非最后一个元素, 那么多值结果会被 省略,只剩下第一个, 如果作为最后一个元素,那么就会保留所有结果.

    function f()
    return 1, 2, 3
    end
    
    local a
    local b
    local c
    f()
    print(a, b, c)
    
    a, b, c = f(), 4, 5
    print(a, b, c)
    
    a, b, c = f()
    print(a, b, c)
    
    a, b, c = 9, 8, f()
    print(a, b, c)
    
    $ luajit t.lua 
    nil	nil	nil
    1	4	5
    1	2	3
    9	8	1
    
  • == ~= < > <= >= 总是产生布尔值. 数字和字符串比较值,对象(tables, userdata, threads, functions)比较引用值.

  • and, or, not其中 andor 支持条件短路. 所以如果第一个参数是 false 或者 nil 就返回第一个参数,否则返回第二个参数.

  • .. 连接字符串

    > print("hello" .. 1)
    hello1
    
  • length. 通过 # 号取出长度, 对字符串来说是bytes的个数,对table来说,是最后一个 非空值的index. 例如 a[1], a[2], a[3] 为1, 而 a[4] 为nil, a[5] 为2, 那么 长度为3.

    local a = {1, 2, 3, nil, 4}
    
    print(#a)
    
    $ luajit t.lua 
    3
    

坑啊,table支持空洞额…

  • 每次遇到local关键字,都会新建一个变量。如果在for循环里local的话,就会新建 循环次数个变量。

  • metatables

lua中每个值都有metatable,其中的key称为events,值称为metamethods. 每个events 的名字都是两个下划线开头,例如 __add。主要包括以下方法:

- add +
- sub -
- mul *
- div /
- mod %
- pow ^
- unm -负号
- concat .. 字符连接号
- len # 号
- eq `==`
- lt <
- le <=
- index `table[key]`
- newindex `table[key] = value`
- call

此外,thread,function和userdata这三种类型的对象还有一个table与之相关,叫做 encironment。thread的环境变量在thread内共享,userdata和c函数在c函数内共享。 非嵌套lua函数和创建的thread共享,嵌套的lua函数和嵌套的lua函数共享。

lua thread级别的envrionment table就是全局变量。可以通过 getfenvsetfenv 获取和修改。

  • coroutine 内置coroutine算是lua的一个特色了

    • coroutine.create 返回新创建的coroutine的handle
    • coroutine.resume 开始执行coroutine
    • coroutine.yield 交出执行权
    • coroutine.wrap 返回一个函数,每次调用都会执行到上一个yield的地方

      local newThread = coroutine.wrap(function()
      print("hello")
      local a = coroutine.yield()
      print(a)
      end)
      
      newThread()
      newThread("haha")
      
  • C-API和C交互的库 略过。

  • 标准库 略过。

  • lua中 x:foo() 相当于 x.foo(x),是一种语法糖。

  • lua的index从1开始。


更多文章
  • Redis源码阅读:执行命令
  • Redis源码阅读:启动过程
  • WAL(Write-ahead logging)的套路
  • 搞定CORS问题
  • 如何定位程序问题所在
  • 设计一个IM归档系统
  • logrotate read only filesystem问题
  • Golang GIN写单测时,愉快的使用返回值
  • Python Queue源码分析
  • Go里优雅的使用全局配置
  • Golang sync.Map源码分析
  • Android滑动时隐藏FAB
  • Python中用tuple作为key
  • 一些常用的算法思维
  • 编写可维护的函数