表达式用于表示值。Lua的表达式中可以包含数字常量、字面字符串、变量、一元和二元操作符及函数调用。另外有别于传统的是,表达式中还可以包括函数定义和构造式。

      

    1. +(加法)、-(减法)、*(乘法)、/(除法)、^(指数)、%(取模)、-(负号)
    1. 例如:
    2. x^0.5 将计算x的平方根
    3. x^(-1/3) 将计算x立方根的倒数
    1. 取模操作符是根据以下规则定义的:
    2. a%b == a - floor(a/b)*b
    3. 例如:
    4. x%1 的结果就是x的小数部分
    5. x - x%1 的结果就是其整数部分
    6. x - x%0.01 则是x精确到小数点后两位的结果
    7. x = math.pi
    8. print(x - x%0.01) --> 3.14

      

      • 关系操作符

    1. <、>、<=、>=、==、~=
    2. 所有这些操作符的运算结果都是true或false。
    3. 操作符==用于相等性测试,操作符~=用于不等性测试。
    4. 这两个操作符可以应用于任意两个值。
    5. 如果两个值具有不同的类型,Lua就认为它们是不相等的。
    6. 否则,Lua会根据它们的类型来比较。
    7. nil只与其自身相等。
    8. 对于table、userdata和函数,Lua是作引用比较的。
    9. 也就是说,只有当它们引用同一个对象时,才认为它们相等。
    1. a = {}; a.x = 1; a.y = 0
    2. b = {}; b.x = 1; b.y = 0
    3. c = a
    4. 其结果是a==c,但a~=b

      

    1. 与条件控制语句一样,所有的逻辑操作符将falsenil视为假,而将其他的任何东西视为真。
    2. 对于操作符and来说,如果它的第一个操作数为假,就返回第一个操作数;不然返回第二个操作数。
    3. 对于操作符or来说,如果它的第一个操作数为真,就返回第一个操作数;不然返回第二个操作数。
    1. print(4 and 5) --> 5
    2. print(nil and 13) --> nil
    3. print(false and 13) --> false
    4. print(false or 5) --> 5
    1. 操作符not永远只返回truefalse
    2. print(not nil) --> true
    3. print(not false) --> true
    4. print(not 0) --> false
    5. print(not not nil) --> false

      

      • 字符串连接

      要在Lua中连接两个字符串,可以使用操作符“..”(两个点)。如果其任意一个操作数是数字的话,Lua会将这个数字转换成一个字符串:

    1. print("Hello" .. "World") --> Hello World
    2. print(0 .. 1) --> 01

      请记住,Lua中的字符串是不可变的值。连接操作符只会创建一个新字符串,而不会对其原操作数进行任何修改:

    1. a = "Hello"
    2. print(a .. "World") --> Hello World
    3. print(a) --> Hello

      

    1. |优先级|
    2. |:--|
    3. |`^`|
    4. |`not``#``-`(一元)|
    5. |`*``/``%`|
    6. |`+``-`|
    7. |`..`|
    8. | `<``>``<=``>=` `~=` `==`|
    9. |`and`|
    10. |`or`|

        在二元操作符中,除了指数操作符“^”和连接操作符“..”是“右结合”的,所有其他操作符都是“左结合”的。因此,下例中左边的表达式等价于右边的表达式:

    1. a + i < b/2 + 1 <--> (a+i) < ((b/2) + 1)
    2. 5 + x^2 * 8 <--> 5 + ((x^2) * 8)
    3. a < y and y <= z <--> (a < y) and (y <= z)
    4. -x^2 <--> -(x^2)
    5. x^y^z <--> x^(y^z)

      • table构造式

      构造式是用于创建和初始化table的表达式。这是Lua特有的一种表达式,并且也是Lua中最有用、最通用的机制之一。

      最简单的构造式就是一个空构造式{},用于创建一个空table。构造式还可以用于初始化数组。元素之间可以用逗号也可以用分号,最后一个元素后面写逗号也是合法的。

    1. days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}

      会将days[1]初始化为字符串“Sunday”、days[2]初始化为“Monday”,以此类推。

      

      Lua还提供了一种特殊的语法用于初始化记录风格的table

    1. a = {x=10, y=20}

      以上这行代码等价于这些语句:

      无论使用哪种方式来创建table,都可以在table创建之后添加或删除其中的某些字段:

    1. x = {math.sin(0), math.sin(1), math.sin(2)}
    2. w[1] = "another field" -- 添加key 1table w
    3. x.f = w -- 添加key "f"table x
    4. print(w["x"]) --> 0
    5. print(w[1]) --> another field
    6. print(x.f[1]) --> another field
    7. w.x = nil -- 删除字段"x"

      

      每当Lua评估一个构造式时,都会先创建一个新table,然后初始化它。

    1. -- table实现链表:
    2. list = nil
    3. for line in io.lines() do -- 从标准输入读取每行的内容
    4. list = {next=list, value=line} -- 按相反的次序存储到一个链表中
    5. end
    1. -- 遍历该链表
    2. local l = list
    3. while l do
    4. print(l.value)
    5. l = l.next
    6. end

      将记录风格的初始化与列表风格的初始化混合在一个构造式中使用:

    1. polyline = {
    2. color = "blue", thickness = 2, npoints = 4,
    3. {x = 0, y = 0},
    4. {x = -1, y = 0},
    5. {x = -10, y = 1},
    6. {x = 0, y = 1}
    7. }

      上例演示了如何通过嵌套的构造式来表示复杂的数据结构。每个polyline[i]元素都是一个table,表示一条记录:

    1. print(polyline[2].x) --> -1
    2. print(polyline[4].y) --> 1

      这两种风格的构造式各有其限制。例如,不能使用负数的索引,也不能用运算符作为记录的字段名。

      

      为了满足这些要求,Lua还提供了一种更通用的格式。这种格式允许在方括号之间,显式地用一个表达式来初始化索引值:

    1. opnames = { ["+"] = "add", ["-"] = "sub", ["*"] = "mul", ["/"] = "div" }
    2. i = 20; s = "-"
    3. a = {[i+0] = s, [i+1]=s..s, [i+2]=s..s..s}
    4. print(opnames[s]) --> sub
    5. print(a[22]) --> ---
    1. 构造式{x=0, y=0}等价于{["x"]=0, ["y"]=0}

      

      对于某些情况如果真的需要以0作为一个数组的起始索引的话,通过这种语法也可以轻松做到:

      现在第一个值“”的索引就为0了。这个索引0并不影响其他元素,“Monday”照常索引为1,因为它是构造式中列表风格中的第一个值,后续其他值的索引依次递增。但无论是否使用这种初始化语法,都不推荐在Lua中以0作为数组的起始索引。大多数内建函数都假设数组起始于索引1,若遇到以索引0开始的数组,它们就无法进行正确地处理了