表达式
在之前的例子中,已经多次用到了表达式,常见的表达式中会用到 大于,小于,等于,不等于等这样条件判断。还有一些其他的用法,比如逻辑连接,IF-ELSE 等
逻辑连接
逻辑连接在之前的例子中是用过的,主要是 /\ (and) ,/ (or),用来将表达式连接起来,有个点需要注意的是,逻辑连接符是空格敏感的,如果以缩进方式开始连接,则TLA+将其视为前一表达式的子表达式。例如
/\ TRUE
\/ TRUE
/\ FALSE \* 相当于 (TRUE \/ TRUE) /\ FALSE
/\ TRUE
\/ TRUE
\/ FALSE \* 相当于 TRUE \/ TURE \/ FALSE
\/ TRUE
\/ TRUE
/\ FALSE \* 相当于 TRUE \/ (TRUE /\ FALSE)
一般规则:
- 如果两个逻辑运算符处于同一缩进级别,则他们属于同一级别的表达式
- 如果逻辑运算符有更多的缩进,则他是前一个运算符语句的一部分
- 每个缩进级别仅使用一种类型的运算符。
个人建议将逻辑运算符使用括号来区别,而不是使用缩进,因为缩进错误导致的bug是比较难发现的。
LET-IN
任何表达式都可以使用 LET-IN 将本地运算符和定义单独添加到该表达式。
LET IsEven(x) == x % 2 = 0 \* 定义临时操作符IsEven(x)
IN IsEven(5)
LET IsEven(x) == x % 2 = 0 \* 如果同时需要定义多个,建议分成多行来保证易读性。写到一行用空格分隔即可
Five == 5
IN IsEven(Five)
LET IsEven(x) == LET Two == 2
Zero == 0
IN x % Two = Zero
Five == 5
IN IsEven(Five)
IF-THEN-ELSE
与其他语言中的if-else功能相同,但在TLA+中IF 必须有与之搭配的ELSE。
IsEven(x) == IF x % 2 = 0
THEN TRUE
ELSE FALSE
Case
Case是条件分支,可以认为是多个IF-ELSE,格式如下:
CASE x = 1 -> TRUE
[] x = 2 -> TRUE
[] x = 3 -> 7
[] OTHER -> FALSE \* OTHER 是需要的,否则当x不满足上述条件是,TLA+将报错
需要注意的是,CASE的分支选择不是从上到下的(例如go语言有条件满足后就直接break),例如以下写法将产生不确定的结果
CASE TRUE -> FALSE
[] TRUE -> TRUE \* 该写法结果可能是FALSE,也可能是TRUE
嵌套
表达式可以嵌套使用,上述例子已经说明了这一点。