kay*_*kay 24 erlang boolean-expression short-circuiting
我很好奇为什么逗号<,>是一个快捷方式and
而不是andalso
保护测试.
由于我称自己为"C native",我没有看到短路布尔评估的任何缺点.
我使用to_core
标志编译了一些测试代码,以查看实际生成的代码.使用逗号,我看到左手值,右边和值得到评估,并且两者都是和.随着andalso
你的情况下块内的情况下块,并没有呼叫erlang:and/2
.
我没有进行基准测试,但我敢说andalso
变体是更快的.
rvi*_*ing 25
深入研究过去:
最初在守卫中只有,
分开的测试,这些测试是从左到右进行评估,直到没有更多,防守成功或测试失败,整个防守失败.后来;
被添加以允许同一条款中的替代警卫.如果警卫,
在测试之前对两侧进行了评估,那么有人在此过程中会遇到错误.@Kay的例子似乎暗示他们确实应该从左到右.
布尔运算符只允许在守卫中使用很久.
and
,with or
,xor
和not
,是一个布尔运算符,不用于控制.他们都是严格的,并首先评估自己的论点,像算术运算符+
,-
,*
和"/".C中也存在严格的布尔运算符.
短路控制操作员andalso
和orelse
后来加入到简化一些代码.正如您所说,编译器确实将它们扩展为嵌套case
表达式,因此使用它们没有性能提升,只是方便和清晰的代码.这将解释您看到的结果代码.
在警卫中注意有测试,而不是表达.有一个微妙的区别,这意味着虽然使用and
和andalso
相当于,
使用orelse
不等同;
.这留给另一个问题.提示:这都是关于失败的.
因此,无论and
并且andalso
有自己的位置.
Adam Lindbergs 链接是对的.使用逗号确实生成比使用和更好的波束代码.我使用+ 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.
Run Code Online (Sandbox Code Playgroud)
产生
{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.
Run Code Online (Sandbox Code Playgroud)
我只研究了使用+ to_core标志生成的内容,但显然在to_core和to_asm之间有一个优化步骤.
布尔运算符“和”和“或”总是评估运算符两侧的参数。而如果您想要 C 运算符&&和|| 的功能 (仅在需要时才评估第二个论点......例如,如果我们想在发现第一个论点为真时立即评估“真或假”,则不会评估第二个论点,这不是这种情况“或“被使用)去” andalso “和”否则别指望”。