表达式

  1. 算术操作符
  2. 关系操作符
  3. 逻辑操作符
  4. 字符串连接
  5. 优先级
  6. table构造式

  

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

  

  • 算术操作符

  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
Lua会在遇到字符串和数字的大小比较时引发一个错误,例如2<"15"就会导致这种错误。

  

  • 逻辑操作符

  1. andornot
  2. 与条件控制语句一样,所有的逻辑操作符将falsenil视为假,而将其他的任何东西视为真。
  3. 对于操作符and来说,如果它的第一个操作数为假,就返回第一个操作数;不然返回第二个操作数。
  4. 对于操作符or来说,如果它的第一个操作数为真,就返回第一个操作数;不然返回第二个操作数。
  1. print(4 and 5) --> 5
  2. print(nil and 13) --> nil
  3. print(false and 13) --> false
  4. print(4 or 5) --> 4
  5. print(false or 5) --> 5
  1. andor都是用“短路求值”,也就是说,它们只会在需要时才去评估第二个操作数。
  2. 短路求值可以确保像(type(v)=="table" and v.tag == "h1")这样的表达式不会导致运行时错误。
  3. 有一种常用的Lua习惯写法“x = x or v”,它等价于:
  4. if not x then x = v end
  5. 另外,还有一种习惯写法是“(a and bor c”,这类似于C语言中的表达式a?b:c,但前提是b不为假。
  6. 例如,为了选出数字xy中的较大者,可以使用以下语句:
  7. max = (x > y) and x or y
  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}

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

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

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

  1. w = {x=0, y=0, label="console"}
  2. x = {math.sin(0), math.sin(1), math.sin(2)}
  3. w[1] = "another field" -- 添加key 1table w
  4. x.f = w -- 添加key "f"table x
  5. print(w["x"]) --> 0
  6. print(w[1]) --> another field
  7. print(x.f[1]) --> another field
  8. 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}
  2. 构造式{"r", "g", "b"}等价于{[1]="r", [2]="g", [3]="b"}

  

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

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

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

  

?