30.if语句会对Guard子句做catch,所以 if 1/0 ->a; true ->b end.的返回值是b而不是抛出异常
Eshell V5.9 (abort with ^G)
1> F = fun(X) -> if 1/0 -> a; true -> b end end.
#Fun<erl_eval.6.111823515>
2> F(1).
b
3> G=1/0 , if G->a; true ->b end.
** exception error: bad argument in an arithmetic expression
in operator '/'/2
called as 1 / 0
if
GuardSeq1 ->
Body1;
...;
GuardSeqN ->
BodyN
end
The branches of an if-expression are scanned sequentially until a guard sequence GuardSeq which evaluates to true is found. Then the corresponding Body (sequence of expressions separated by ',') is evaluated.
Note: I've compared
,
and;
in guards to the operatorsandalso
andorelse
. They're not exactly the same, though. The former pair will catch exceptions as they happen while the latter won't. What this means is that if there is an error thrown in the first part of the guardX >= N; N >= 0
, the second part can still be evaluated and the guard might succeed; if an error was thrown in the first part ofX >= N orelse N >= 0
, the second part will also be skipped and the whole guard will fail.However (there is always a 'however'), onlyandalso
andorelse
can be nested inside guards. This means(A orelse B) andalso C
is a valid guard, while(A; B), C
is not. Given their different use, the best strategy is often to mix them as necessary.
上图是对官方文档的重新组织表达
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, will not be evaluated.)
Guard1;...;GuardKA guard is a sequence of guard expressions, separated by comma (,). The guard is true if all guard expressions evaluate to true.
GuardExpr1,...,GuardExprNThe set of valid guard expressions (sometimes called guard tests) is a subset of the set of valid Erlang expressions. The reason for restricting the set of valid expressions is that evaluation of a guard expression must be guaranteed to be free of side effects. Valid guard expressions are:
- the atom true,
- other constants (terms and bound variables), all regarded as false,
- calls to the BIFs specified below,
- term comparisons,
- arithmetic expressions,
- boolean expressions, and
- short-circuit expressions (andalso/orelse).
Ah, I understand what you mean, you're right there. If LYSE were to be more of a reference manual, I would definitely update the definition to reflect this. However, I feel it might be going against the tone to go with such strict definitions.I made the same choice when it came to explaining that 'functions end in a .' and that module attributes do the same. I could have used the broader distinction between forms and expressions, that ',' act as expression separators, ';' act as branch separators, and that '.' terminate forms (do not separate them), but that the Erlang shell breaks the rules by using '.' as a way to end expressions, which isn't valid by the modules' definitions. However, while the strict definition is 100% true, it isn't the easiest thing when it comes to learning, in my opinion.My definition wouldn't work for someone writing a parser, and it wouldn't work for someone who wants to understand the absolute truth about the language, I however feel it helps in understanding the concept of guards when you have never encountered it before. It's a bit how we could teach children that pi is '3.1416' and let them use this as a notion; they need not to know that pi is irrational, that it has an infinite amount of digits, etc.You may disagree with me on the approach, but I do believe it works rather well.By the way, thanks for writing me about this :) I'm enjoying the discussion.Regards,Fred.