Erlang:列表理解过滤器短路

时间:2017-08-31 20:26:50

标签: erlang

让我说我有:

 [ X || X<- L, some_expensive_boolean(X), some_expensive_boolean2(X)]

对于任何X in Lsome_expensive_boolean(X)是否为falsesome_expensive_boolean2(X)是否已执行?

4 个答案:

答案 0 :(得分:3)

基于以下内容的短路:

${GEN_HEADER_A}

执行:

-module(shortcircuit).

-export([test/0]).

test() ->
  L = [1, 2, 3],
  [ X || X <- L, some_expensive_boolean(X), some_expensive_boolean2(X)].

some_expensive_boolean(X) ->
  io:format("In some_expensive_boolean: ~p~n", [X]),
  false.

some_expensive_boolean2(X) ->
  io:format("In some_expensive_boolean2: ~p~n", [X]),
  true.

答案 1 :(得分:3)

答案是否定的。它被短路了。

1> [ X || X <-[1,2], begin io:format("Test 1: ~p~n", [X]), X rem 2 =:= 0 end, io:format("Test 2: ~p~n", [X]) =:= ok ].
Test 1: 1
Test 1: 2
Test 2: 2
[2]

答案 2 :(得分:3)

TL; DR:不,some_expensive_boolean2/1未被调用。

有几种方法可以验证这一点。

1。让函数在调用时打印一些东西。

-module(lc).

-export([lc/1]).

lc(L) ->
  [X || X <- L, f(X), g(X)].

f(X = 2) ->
  erlang:display({f, 2}),
  false;
f(X) ->
  erlang:display({f, X}),
  true.

g(X) ->
  erlang:display({g, X}),
  true.

然后在Erlang shell上:

1> lc:lc(lists:seq(1, 4)).
{f,1}
{g,1}
{f,2} %% g is not called here
{f,3}
{g,3}
{f,4}
{g,4}
[1,3,4]

2。检查生成的Core Erlang代码。

使用+to_core选项编译模块将生成带有Core Erlang代码的lc.core文件,该文件看起来有点像Erlang,但有自己的语法,但语义非常相似。

erlc +to_core lc.erl

生成的代码非常详细,所以我不会在这里粘贴它,但要点是有两个嵌套的case表达式,一个调用f/1,其子句与{匹配{1}}包含调用true的其他case

答案 3 :(得分:1)

让我们创建一个例子:

$ cat test.erl
-module(test).

-export([show/0]).

show() ->
   [ X || X <- [1,2,3,4,5], bigger(X), smaller(X)].

bigger(X) ->
   io:format("bigger ~p~n", [X]),
   X > 2.

smaller(X) ->
   io:format("smaller ~p~n", [X]),
   X < 4.

并测试它:

14> c(test).
{ok,test}
15> test:show().
bigger 1
bigger 2
bigger 3
smaller 3
bigger 4
smaller 4
bigger 5
smaller 5
[3]

所以答案是:NO。