第二个测试....ListsRec5.all?(1..7, true, fn x -> x
我认为第二个测试应该返回 true,而不是一个空列表。
好吧,让我们看看:
iex(3)> true and []
[]
iex(4)> true and []
[]
iex(5)> true and []
[]
iex(6)> true and []
[]
iex(7)> true and []
[]
iex(8)> true and []
[]
iex(9)> true and []
[]
是的,这是一个空列表。我读过:
and 需要布尔参数并返回一个布尔值。
and 要求第一个参数是布尔值并返回一个布尔值。
上面的例子反驳了这两个不称职的说法。所以,让我们忽略 Elixir 作者徒劳地试图解释 and 是如何工作的,因为显然 Elixir 中的 and 等同于 Erlang 中的 andalso。所以让我们检查一下 Erlang docs:
Expr1 andalso Expr2
返回 Expr1 的值 (false) 或
Expr2 的值(如果计算了 Expr2)。
因此,如果 Expr1 为真,则 andalso 返回 Expr2,否则,andalso 返回 false,即当 Expr1 为假时。
从 Erlang/OTP R13A 开始,不再需要 Expr2 来评估
布尔值。
这解释了为什么你得到一个空列表:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> true andalso false.
false
2> true andalso [].
[]
3> true andalso 10.
10
4> false andalso "hello".
false
还要注意这里:
def all?(enumerable, acc, fun \\fn x -> x end) do
enumerable
|> Enum.reduce([], fn x, acc -> fun.(x) and acc end)
end
那acc 变量在所有? def 的参数列表未使用。函数应该这样定义:
def all?(enumerable, acc, fun \\fn x -> x end) do
enumerable
|> Enum.reduce(acc, fn x, curr_acc -> fun.(x) and curr_acc end)
end
那么你可以这样称呼它:
~/elixir_programs$ iex a.ex
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> A.all?(1..7, true, fn x -> x<8 end)
true
iex(2)> A.all?(1..7, true, fn x -> x<7 end)
false
在循环中的某处你会得到acc=true and false,它返回false,然后false and anything 将返回false。因此,如果谓词函数为枚举中的任何元素返回false,那么最终结果将是false。