test_guard_zero(X) when not ((X rem 0) =:= 0) ->
io:format("0 can't pass~n");
test_guard_zero(_X) ->
io:format("zero~n").
test_guard_andalso(X) when not(X =/= 0 andalso ((X / 0) =:= 0)) ->
io:format("andalso 0 can pass~n").
test_guard_orelse(X) when X =:= 0 orelse ((10 rem X) =:= 0) ->
io:format("orelse 0 can pass~n").
test_guard_and(X) when not(X =/= 0 and ((X / 0) =:= 0)) ->
io:format("and when X = 0 will exception error~n").
test_guard_or(X) when X =:= 0 or ((10 rem X) =:= 0) ->
io:format("or when X = 0 will exception error.~n").
%% test_guard_comma(X) when not(X =/= 0, (10 rem X =:= 0)) ->
%% 这里发现 not 后面不能跟多个表达式,上面这一条语句语法错误,记录一下
test_guard_comma(X) when X =/= 0, (10 rem X =:= 0) ->
io:format("comma useless ~n");
test_guard_comma(_X) ->
io:format("can't judge").
test_guard_semicolon(X) when X =:= 0; X rem 0 =:= 0 ->
io:format("semicolon 0 can pass~n").
首先我们需要先证明上面所说的布尔表达式和短路布尔表达式的区别
下面看上述代码执行结果,为了节省空间,省略了打印的 ok:
1> c(test_guard).
{ok,test_guard}
2> test_guard:test_guard_zero(0).
zero
5> test_guard:test_guard_and(0).
** exception error: no function clause matching
test_guard:test_guard_and(0) (test_guard.erl, line 28)
6> test_guard:test_guard_or(0).
** exception error: no function clause matching
test_guard:test_guard_or(0) (test_guard.erl, line 30)
这两条输出表明「and, or」会求出所有表达式的值,所以由于除 0 异常导致当前匹配失败,从而整个函数的模式匹配失败,造成「no function clause matching」的异常
以上证明了短路布尔表达式和布尔表达式的区别
接下来看我们要讨论的正题:
7> test_guard:test_guard_comma(0).
can't judgeok
8> test_guard:test_guard_semicolon(0).
semicolon 0 can pass
ok
首先 test_guard_comma 这条输出结果证明不了任何事,因为不知道是因为短路求值的 false 导致进入第二个分支,还是因为非短路求值第二个表达式异常造成匹配失败从而进入到第二个分支。而由于 not 后面不能跟逗号连接的表达式,所以无法像上面 and 和 andalso 那样来匹配。
然后我们看分号表达式的输出结果,发现分号的作用在这里相当于 orelse,因为上面已经知道了如果是 or 这里会发生异常。
所以这里的分号和逗号代表什么,暂时我还不确定,等搞清楚了再来补充。
modified at 23:40, 27 May
这里还是要理清楚 Guard 和「Guard Sequence」的概念,
A guard sequence is a sequence of guards, separated by semicolon (. The guard sequence is true if at least one of the guards is true. (The remaining guards, if any, are not evaluated.)
.
Guard1;…;GuardK
.
A guard is a sequence of guard expressions, separated by comma (,). The guard is true if all guard expressions evaluate to true.
.
GuardExpr1,…,GuardExprN
.
The set of valid guard expressions (sometimes called guard tests) is a subset of the set of valid Erlang expressions.