第03章 表达式

表达式是有量(变量或常量)与运算符(显示或隐式)组成的语句。

算数操作符

Lua 的算术操作符有如右几个:+ - * / ^ % 都用于实数计算,有几个和 Java 中有些区别,单独介绍如下:

  • ^ 乘方,如 x^0.5, x^2 分别是开根号和平方
  • % 的定义: a%b == a - floor(a/b)*b,因为它的运算范围也是实数域,所以有些奇怪的表现,比如 x%1 得到了 x 的小数部分,x-x%1 得到了 x 的整数部分, x - x%0.001 表示 x 截取到小数位后第三位(没有四舍五入)。

另外,- 也可以是一元操作符的负号。

关系操作符

Lua 的关系操作符有如右几个: < > <= >= == ~=,有几点需要注意的:

  • ~= 不等号,注意,不能用 C 的 !=
  • 大小性的比较,只能是两个数字或者两个字串来做,即数字只能和数字做比较,字串只能和字串做比较,如果把数字和字串做比较,程序会出错。字串比较是按字母次序来比较的,如:print("a" < "b") --> true

逻辑操作符

Lua 的逻辑操作符有三个:and or not

Lua 的逻辑运算认为只有 false nil 是假(false),其他为真,0也是 true. 不知道 C 中是具体返回操作量的值,还是返回 true/false? 貌似 C 中对 true /false 的规定和 Lua 有些差别,待查 TODO。

or 和 and 运算的返回值,这可能是 lua 相对其他语言,比较变态的地方,它并不限定返回逻辑值 true/false,而是返回操作量的值(这点和 Java 很不一样,Java 的习惯是,只返回 true/false),具体规定如下:

  • a and b -- 如果 a 为 false,则返回 a,否则返回 b。这其实是短路运算的结果,如果 a 为 false,因为是 and 运算,肯定表达式的值就是a,否则,就是b
  • a or b -- 如果 a 为 true,则返回 a,否则返回 b。这也是短路运算的结果。
  • or, and 都使用 short-cut evaluation(短路求值)

书上说 (a and b) or c 等价于 C 中的 a ? b : c ,可实际情况并非完全如此,如:

a, b, c = true, false, 0909
print((a and b) or c)

将输出909, 即 c 的值——在 a 为 true 时,输出的不是 b 的值。只有在 b ~= false 时, (a and b) or c 才等价于 C 中的 a ? b : c ,此时可以如此解释:如果 a 为 true,值决定于 b,如果 a 为 false,值决定于 c。

not 运算符只返回 true/false

不同语言中的逻辑运算可以专门记录一下:TODO《C, Lua, Java, JavaScript 中的逻辑运算比较》

字符串连接

Lua 的字符串连接使用双点号 .. ,这个和 Java 中使用 + 也是不一样的。具体在使用上,要注意:

  • 不要把数字和字串来做连接,也不要把 nil 和字串去做连接,最好把需要连接的量显示转为 string 再操作。
  • 双点号的左右应该各有一个空格,美观,而且,左边要是没空格,会被误认为是小数点,引起报错。

TODO 列举几个实例

TODO 比较一些不同语言的字符串连接:Java: +, C: ?, JavaScript: +, Oracle SQL: ||, Python: ?, Linux shell: ?

运算符的优先级

虽然运算符有优先级的规定,但建议多用括号,以明确含义,增强程序的可读性和可维护性。

     or
     and
     <     >     <=    >=    ~=    ==
     ..
     +     -
     *     /     %
     not   #     - (unary)
     ^

(运算优先级,从上往下逐渐增高)

table constructor

(这部分内容,暂时整理到本系列的《第二章 类型和值》里去了,将来再重新整理。TODO)