Lua简要笔记-1
2015年03月24日 Lua

Lua简要笔记。

Hello, World

  1. 直接在命令行运行(前提lua已加入环境变量中):

    >>print(“Hello, World!”)

  2. print语句写在文件中,如hello.lua, print(“Hello, World!”)保存
    在文件所在目录打开命令行,然后再执行命令:

    lua hello.lua

  3. lua还提供一个e选项可以直接在命令行中执行lua代码:

    lua -e “print(‘Hello, World!’)”

  4. lua也可以像c语言一样支持命令行参数,然后在lua中捕获这些参数值
    参数值都存在一个arg的全局表中

    1
    2
    3
    4
    -- 直接输出包括脚本文件名称在内的所有参数
    for i = 0, table.getn(arg) do
    print(arg[i])
    end

    lua test.lua arg1 arg2 arg3

注释

  • 单行注释,二个连续的中划线”–”,一行内二个中划线后的内容就被认为是注释内容

    1
    -- single line comment in lua
  • 多行注释,以”–[[“开头,然后以”]]”结尾的部分都会被认为是多行注释(块注释)

    1
    2
    3
    4
    --[[
    muilti line comment in lua
    by bugcode
    ]]

    变量定义

  • 全局变量

    在lua中因为是脚本语言,不需要声明,需要变量的时候直接定义使用(就是需要的时候拿过来用)

    不需要类型关键字等信息,定义的这些变量都是全局变量。

    1
    2
    3
    4
    --未加local标识符,下面定义的都是全局变量
    var_def_num = 12 --定义了一个数值变量
    var_def_str = 'string' --定义了一个字符串
    var_def_bool = false --定义了一个布尔类型
  • 局部变量

    如果你想定义一下局部变量,需要在变量前加”local”关键字。应该尽可能使用局部变量,因为一来可以避免冲突,二来局部变量访问速度快于全局变量

    1
    local var_def_loc_num = 20 --定义了一个局部变量

各种类型

可以通过lua的内置函数type来得知每个变量的类型,type函数返回一个字符串

1
2
3
print(type("string"))--string
print(type(type))--function
print(type(nil))--nil
  • nil

    nil表示没有使用过的变量,一个使用过的全局变量赋值为nil即表示删除了这个变量。

    nil是值,也是一个类型,可以直接给一个变量赋值为nil。

    1
    var_global = nil
  • 布尔类型

    falsetrue,只有false与nil表示false,其他的所有都表示为true(包括数值0与空字符串””)

    也可以直接给变量赋值false或者true。

    1
    local boolean = false
  • 数值类型

    在lua中数值只有一种,就是c语言中的double,并不会有浮点数的效率问题,下面的赋值都是合法的

    1
    2
    3
    4
    var_int = 12
    var_float = 20.01
    var_math = 1.34e12
    var_math_neg = 0.12e-12
  • 字符串

    定义与使用,lua中比较常用的一种数据类型,可以处理_量_很大的字符串,定义的方式就是使用单引号或者双引号括起来都可以。

    1
    2
    var_string_dou_qt = "string in lua with double quot"
    var_string_sig_qt = 'string in lua with single quot'
  • 转义

    在lua中也如c语言中,支持一些转义字符,如换行,响铃之类,如下:

    | 符号 | 含义 |
    | :–: | :—-: |
    | \a | 响铃 |
    | \b | 退格 |
    | \f | 换页 |
    | \n | 换行 |
    | \r | 回车 |
    | \t | 横向制表 |
    | \v | 纵向制表 |
    | \ | 转义 |
    | \” | 双引号 |
    | \’ | 单引号 |
    | [] | 左,右中括号 |

    lua中也支持使用\xxx的方式表示字符(x为一个十进制的数字),如\049就是数字1,\98就是小写字母b。
    有些情况就是使用一些大段的字符串,而且显示的时候需要换行,这样就会在单行的字符串中出现多个\n之类的转义字符出现
    可能美观上不太好看,lua提供了另一个字符串的表示方法,就是用”[[“与”]]”将要显示或者处理的字符串括起来,那么二个[[与]]之间的字符串就会是保持原样。

    1
    2
    3
    4
    var_string_in_bracket = [[
    keep origion style string in lua
    that use double square bracket
    ]]
  • 字符串连接

    先提一下字符的连接是”..”使用二个句点连接字符串:

    1
    2
    var_str = "prefix_string"
    print(var_str .. "_middle_string" .. "_suffix_string")

    输出的就是_prefix_string_middle_string_suffix_string_。

    lua中的字符串是定义后是不可修改的(类似于c语言中的字符串字面量),但是可以用一个新的字符串变量接收修改后的字符串。这里的字符串也是不需要手动分配内存与释放内存的,都是lua自动分配与释放的。

    1
    2
    3
    4
    5
    var_str = "string for lua"
    --这里并没有改动var_str的内容,而是返回了一个新的字符串,被str_res接收
    var_res = string.gsub(var_str, "lua", "python")
    print("var_res: " .. var_res)
    print("var_str: " .. var_str)
  • 字符串与数值的互转

    lua会自动的在字符串与数值类型间相互转换,比如对一个字符串进行数值上才有的操作时,这时字符串就会转为数值,会在期望一个数值的地方将字符串转为数值,如果期望数值的地方不是数值或者转不成数值就会报错。同理,在期望一个字符串的地方遇到了数值,就会把数值转换成字符串。

    1
    2
    3
    4
    5
    -- 此时"25"会转换为数值25,var_rst就是37
    var_rst = "25" + 12
    print("12" * "4")--输出48
    print("12" * "str")--报错,期望str是一个数值然后与12做乘法,但是str无法转换成数值,报错!
    print(100 .. 200) -- 100200,数字后的连接符号前要有空格,不然可能会被解释错。

函数
在lua中函数也是一个类型,也就是表示,函数在lua可以当做参数,可以赋值给变量,可以做为函数的返回值
定义方法,function关键字,end结束

1
2
3
function lua_function(param)
--todo
end
  • Userdata和Threads

    userdata是c中的定义的新数据类型,它可以直接将c中的数据放在lua的变量中,并且userdata在lua中除了赋值与相等操作并没有其他预定义好的操作,threads是协同的时候需要用到的。

表达式

  • 算术运算符

    乘方操作符^,其他与C语言一致,对于减号,如果是二元运算(有二个操作数),表示减法操作,如果一元操作(只有一个操作数)表示取负数,这些运算符的操作数都是实数,也就是上文类型中的数值类型。

  • 关系运算符

    不等于操作等是~=,其他与C语言一致,除了不等于其他都与c语言相同,进行相等比较的时候,在lua中比较二个操作数的值,如果值类型不同,那么lua认为二个值不同,对于userdata,table,function三种数据,lua则是通过比较引用来确定二个对象是否相等,也就是说,单单内部的值相等是不够的,要二个操作数表示的是同一个对象,才相等。

“10” == 10 这是不同类型的二个值,这个表达式生成false
10 > “2” 类似这种数值与字符串的大小比较,lua会直接报错

  • 逻辑运算符

    | 符号 | 作用 |
    | :–: | :–: |
    | and | 与 |
    | or | 或 |
    | not | 非 |

    上文布尔类型的时候说过,lua中除了nil和false是false,其他都是true,逻辑运算也就与c语言相同了
    有二个技巧可以用,因为在lua没有三元运算符,可以这样实现

    1
    2
    -- x ? y : z
    (x and y) or z

    还有一种常用的变量非nil测试并赋值

    1
    2
    3
    4
    5
    x = x or val
    --等价于
    if x == nil then
    x = val
    end

    连接运算

    字符串的时候提到过了,二个句点,用于连接二个字符串,如果操作数是数值类型,则会把数值转换为字符串,但是数值使用连接符号的时候空格是必须的,以防解释错连接符作用

构造表
由构造器(constructor)来构造表,最简单的表的构造

1
tbl = {} -- 这就构造了一个空的表

也可以直接像c语言的数组初始化一样定义的同时初始化表

1
halfy_month_tbl = {"1", "2", "3", "4", "5", "6"}

这就相当于把”1”放在了halfy_month_tbl[1]中,依次类推(lua中索引从1开始,而不是从0开始)
还可以使用类似于键值的方式来初始化表

1
rect_tbl = {wid = 10, hgt = 20, name = "Rectangle"}

此时访问对应的表中的数据,需要使用标签索引,rect_tbl[“wid”] -> 10, rect_tbl[“name”] -> “Rectangle”
也可以使用rect_tbl.hgt来访问hgt域
而且我们可以随时向表中添加或者删除任何类型的域,构造器只是在初始化的时候起作用

1
2
3
4
5
6
7
8
9
10
11
--初始化一个表
ext_tbl = {x = 10, y = 15, desc = "extension"}
tmp_tbl = {is_add = false, z = 10.01}
--向ext_tbl中添加一个域,内容是一个表
ext_tbl["ext"] = tmp_tbl
ext_tbl[1] = "test_area"
--删除ext_tbl的一个域
ext_tbl["x"] = nil
print(ext_tbl[1]) -- "test_area"
print(ext_tbl.ext["z"]) -- 10.01
print(ext_tbl.x) -- nil

因为每次使用构造器的时候都产生一个新的表,可以用这个特性生成一个链表

1
2
3
4
5
6
7
8
9
10
11
linked_list = nil
--构造链表
for i = 1, 20, 2 do
linked_list = {n = linked_list, v = i}
end
--反序输出
tmp = linked_list
while tmp do
print(tmp.v)
tmp = tmp.n
end

表也可以在初始化的时候同时使用没有域名字与有域名字的

1
2
3
4
5
6
7
tbl = {x = 10, y = 30, "first"}
print(tbl.x) -- 10
print(tbl[1]) -- "first"
--还可以使用嵌套表的结构
init_tbl = {name = "table", area = 10, {a = 1, b = 2}, {is_loop = true, has_prefix = false}}
print(init_tbl[1].a) -- 1
print(init_tbl[2].has_prefix) --false

我们不能使用负索引来初始化,还有一种更通用的方式来初始化字符串索引的表,使用[exp] (中括号加字符串的方式来表示字符串索引)

1
2
week_tbl = {["mon"] = 1, ["tues"] = 2, ["wed"] = 3, ["thu"] = 4, ["fri"] = 5, ["sat"] = 6, ["sun"] = 7}
print(week_tbl["mon"]) -- 1

表初化的最后一个域后的逗号是可选的,可加可不加,加上是为了经后的扩展,逗号也可以用分号(;)来替代,通过的做法是
同类型的用逗号,不同类型间的用分号分隔

1
type_tbl = {num = 10, 100; str = "string", "value"; boolean = false, true}

语法

  • 赋值语句

    单变量赋值,像c语言一样,等号左边是变量右边是表达式

    1
    2
    assign_var = 100
    var_str = "pre" .. "str"

    多变量赋值,左边是用逗号分隔开的一个变量的列表,右边是表达式的列表,如果变量数目多于表达式个数,则后面的变量是nil,如果表达式数目多于变量数目,那么多的表达式就会丢弃:

    1
    2
    3
    x, y, z = 100, false, "multi" .. " assignment"
    a, b = 10, 20, 30 --30会被丢弃
    k, l, m = 1, 2 -- m --> nil

    交换变量,在lua中交换二个变量非常简单,反序赋值就可以了

    1
    2
    x = 10; y = 20
    x, y = y, x -- 完成了交换 x --> 20, y --> 10
  • 流程控制语句

    1. if..else

      形式是这样的
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      x = nil
      --单个的if
      if not x then
      x = 100
      end
      --if与else
      if x == 100 then
      x = x - 10
      else
      x = x + 10
      end
      --if..elif..else
      if x == 100 then
      print(x)
      elif x == 10 then
      print("x == 10")
      else
      print("else condition")
      end
    2. while

      形式是

      1
      2
      3
      4
      5
      6
      index = 1
      fact = 1
      while i < 10 do
      fact = fact * i
      end
      print(fact)
    3. repeat..until

      类似于c语言的do..while

      1
      2
      3
      4
      5
      6
      7
      8
      i = 1
      sum = 0
      -- compute 1 to 10 summary
      repeat
      sum = sum + i
      i = i + 1
      until i > 9
      print(sum)
    4. for循环

      普通for循环

      1
      2
      3
      4
      5
      6
      7
      8
      --1 to 20 with 2 increament
      _start = 1 --起始值
      _end = 20 -- 结束值,由start与end构成的
      _step = 2 -- 每次循环i的增量,可为负值
      -- !此处的i是局部变量,只在for循环的作用域内起作用
      for i = _start, _end, _step do
      print(i)
      end

      范型for循环, 通过ipairs与pairs迭代器

      1
      2
      3
      4
      5
      6
      7
      8
      9
      --输出数组中所有的数值
      tbl = {1, 3, 5, 6; false; "end"}
      for i, v in ipairs(tbl) do
      print(v)
      end
      --输出表中的key
      for i in pairs(tbl) do
      print(tbl[i])
      end

      ipairs 只能迭代到表中非整数的key为止,并且不返回nil,只返回0,遇到nil就退出
      pairs 能迭代表中所有的key,并且能返回nil

      1
      2
      3
      4
      5
      6
      7
      8
      9
      tbl_es = {[1] = "11", [2] = "22", [5] = "55", ["six"] = false}
      --只输入11与22,因为迭代到3的时候是nil,遇到nil就直接跳出了
      for i, v in ipairs(tbl_es) do
      print(v)
      end
      --遍历所有的表中的key
      for i in pairs(tbl_es) do
      print(tbl_es[i])
      end
    5. break与return
      break作用与c语言相同都是跳出循环的,在lua中包括while, repeat..while, for循环
      return是从函数中返回值用的,一般的时候都是出现一个语句块的最后,但是如果有需要在中间需要return的时候需要使用do..end括起来形成一个语句块

      1
      2
      3
      4
      5
      6
      7
      8
      9
      function return_test()
      for i = 1, 100, 2 do
      if i == 13 then
      do return end
      else
      print(i)
      end
      end
      end