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”,则不会评估第二个参数,而事实并非如此“”已被使用)选择“和“或”