我能够编写像erlang:'and'(true, false)
这样的前缀布尔表达式,但不能写出相应的andalso
或orelse
表达式。为什么呢?
当我查看核心输出时,看起来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
的疏忽,还是某种“过早扩张”难以理解?
答案 0 :(得分:8)
主要原因是对BIF的调用与调用“普通”函数的行为方式相同,因为它们的参数严格,全部在BIF /函数之前评估参数调用。与andalso
和orelse
区分的是,他们不评估所有参数,只评估第一个参数。然后,根据第一个参数的值,他们可能会或可能不会评估第二个参数。这意味着即使它们是BIFS,它们也必须由编译器进行特殊处理,因此制作它们的BIF几乎没有意义。
此外,扩展也非常简单,因此在他们专门处理BIF时没什么好处。