Erlang 在守卫测试中,什么时候更喜欢“and”而不是“andalso”
我很好奇为什么逗号è,›是警卫测试中Erlang 在守卫测试中,什么时候更喜欢“and”而不是“andalso”,erlang,short-circuiting,boolean-expression,Erlang,Short Circuiting,Boolean Expression,我很好奇为什么逗号è,›是警卫测试中和的快捷方式,而不是和的快捷方式 因为我称自己为“C母语”,所以我看不到短路布尔运算的任何缺点 我使用to_core标志编译了一些测试代码,以查看实际生成的代码。使用逗号,我看到左边的值和右边的和值都被计算,并且都被and'ed。使用andalso在case块中有一个case块,并且没有调用erlang:and/2 我没有做过基准测试,但我敢说,和变体是速度更快的。这是一个历史原因和是在和之前实现的,它是在Erlang 5.1中引入的(我现在能找到的唯一参考是
和的快捷方式,而不是和的快捷方式
因为我称自己为“C母语”,所以我看不到短路布尔运算的任何缺点
我使用to_core
标志编译了一些测试代码,以查看实际生成的代码。使用逗号,我看到左边的值和右边的和值都被计算,并且都被and'ed。使用andalso
在case块中有一个case块,并且没有调用erlang:and/2
我没有做过基准测试,但我敢说,和变体是速度更快的。这是一个历史原因和
是在和
之前实现的,它是在Erlang 5.1中引入的(我现在能找到的唯一参考是)。由于向后兼容,防护装置没有改变。亚当·林德伯格是对的。使用逗号确实比使用andalso生成更好的beam代码。我使用+to_asm标志编译了以下代码:
a(A,B) ->
case ok of
_ when A, B -> true;
_ -> false
end.
aa(A,B) ->
case ok of
_ when A andalso B -> true;
_ -> false
end.
产生
{function, a, 2, 2}.
{label,1}.
{func_info,{atom,andAndAndalso},{atom,a},2}.
{label,2}.
{test,is_eq_exact,{f,3},[{x,0},{atom,true}]}.
{test,is_eq_exact,{f,3},[{x,1},{atom,true}]}.
{move,{atom,true},{x,0}}.
return.
{label,3}.
{move,{atom,false},{x,0}}.
return.
{function, aa, 2, 5}.
{label,4}.
{func_info,{atom,andAndAndalso},{atom,aa},2}.
{label,5}.
{test,is_atom,{f,7},[{x,0}]}.
{select_val,{x,0},{f,7},{list,[{atom,true},{f,6},{atom,false},{f,9}]}}.
{label,6}.
{move,{x,1},{x,2}}.
{jump,{f,8}}.
{label,7}.
{move,{x,0},{x,2}}.
{label,8}.
{test,is_eq_exact,{f,9},[{x,2},{atom,true}]}.
{move,{atom,true},{x,0}}.
return.
{label,9}.
{move,{atom,false},{x,0}}.
return.
我只研究了+to_core标志生成的内容,但显然在to_core和to_asm之间有一个优化步骤。要深入研究过去:
- 最初在guards中只有
,
分离的测试,从左到右进行评估,直到没有更多测试,guards成功,或者测试失败,guards整体失败。后来添加了代码>以允许在同一子句中使用备用保护。如果警卫在测试前评估了,
的两面,那么有人在测试过程中出错了@Kay的例子似乎暗示他们确实应该从左到右
- 布尔运算符只在很久以后才被允许在guards中使用
和
以及或
、异或
和非
是一个布尔运算符,不用于控制。它们都是严格的,首先计算参数,比如算术运算符+
,-
,*
和“/”。C语言中也存在严格的布尔运算符
- 后来添加了短路控制操作符
和和或
,以简化一些代码。正如您所说的,编译器确实将它们扩展到嵌套的case
表达式,因此使用它们不会提高性能,只是代码的方便性和清晰性。这将解释您看到的结果代码
- N.B.防护装置中有测试,没有表达式。有一个微妙的区别,这意味着当使用
和和时,并且等同于,
使用或并不等同于代码>。这是另一个问题。提示:这都是关于失败的
因此和和以及和都有各自的位置。布尔运算符“和”以及“或”总是在运算符的两侧计算参数。然而,如果您想要C运算符的功能&和|(其中第二个参数仅在需要时进行评估..例如,如果我们希望在发现第一个参数为true时立即评估“true或Elsefalse”,则不会评估第二个参数,而事实并非如此“或”已被使用)选择“和“或””