5

我可以写前缀布尔表达式,例如erlang:'and'(true, false),但不能写对应的andalsoororelse表达式。为什么?

当我查看核心输出时,它看起来就像andalso并且orelse只是宏 - 例如:

a(A,B) -> A and B.

转化为核心

'a'/2 =
    %% Line 4
    fun (_cor1,_cor0) ->
        call 'erlang':'and'
            (_cor1, _cor0)

但也来自

b(A,B) -> A andalso B.

'b'/2 =
    %% Line 6
    fun (_cor1,_cor0) ->
        ( case _cor1 of
            ( <( 'true'
                 -| ['compiler_generated'] )> when 'true' ->
                  _cor0
              -| ['compiler_generated'] )
            ( <( 'false'
                 -| ['compiler_generated'] )> when 'true' ->
                  'false'
              -| ['compiler_generated'] )
            ( <_cor2> when 'true' ->
                  ( call ( 'erlang'
                           -| ['compiler_generated'] ):( 'error'
                                                         -| ['compiler_generated'] )
                        (( {( 'badarg'
                              -| ['compiler_generated'] ),_cor2}
                           -| ['compiler_generated'] ))
                    -| ['compiler_generated'] )
              -| ['compiler_generated'] )
          end
          -| ['compiler_generated'] )

看起来它是以这种方式实现的以保持惰性,但它不必在这一步中——例如,仍然可以有call 'erlang':'andalso'一行,稍后翻译。

这只是一个erlang:'andalso'(A,B)不等同于的疏忽A andalso B,还是某种“过早的扩展”使这变得困难?

4

1 回答 1

8

主要原因是对 BIF 的调用与对“普通”函数的调用行为相同,因为它们的参数是严格的,所有参数都在调用 BIF/函数之前进行评估。andalso与and的区别orelse在于它们不会评估所有论点,而只会评估第一个论点。然后根据第一个参数的值,他们可能会或可能不会评估第二个参数。这意味着即使它们是 BIFS,编译器也必须对它们进行特殊处理,因此使它们成为 BIF 几乎没有意义。

此外,扩展非常简单,因此作为他们专门处理 BIF 的做法几乎没有什么收获。

于 2013-07-14T03:39:33.887 回答