Enum.reduce/3
的Elixir帮助页面显示,几乎所有Enum
函数都可以在Enum.reduce/3
之上实现。我正在尝试通过编写使用Enum.all?/1
的新函数来实现Enum.reduce/3
。它在大多数时间都能正常工作,但在某些情况下会返回一个空列表。
在一种情况下,我调用了传递1..7
范围的函数,并测试了一个值小于7
的函数。在另一种情况下,我通过了1..7
范围和一个函数来测试其值小于8
。
在第一种情况下,我的all?/1
函数正确地返回false,因为所有值都不小于7
。
在第二种情况下,我期望为真,所有值均小于8
,但取回一个空列表。
这是我对all?/1
函数的实现.....
defmodule ListsRec5 do
def all?(enumerable, acc, fun \\fn x -> x end) do
enumerable
|> Enum.reduce([], fn x, acc -> fun.(x) and acc end)
end
end
第一次测试……
ListsRec5.all?(1..7, true, fn x -> x < 7 end)
false
第二次测试....
ListsRec5.all?(1..7, true, fn x -> x < 8 end)
[]
我认为第二个测试应该返回true
,而不是空列表。
答案 0 :(得分:2)
如果您要简化为布尔值(在这里减少并不是最好的方法,但是可以做到),则累加器将是布尔值,而不是列表,并且每次迭代都将是一个布尔值表示“所有先验都是真实的,而这一切都是真实的。”
Enum.reduce(enumerable, true, fn x, acc -> acc and fun.(x) end)
答案 1 :(得分:0)
这里的问题是您使用的累加器传递给reduce/3
def all?(enumerable, fun \\fn x -> x end) do
enumerable
|> Enum.reduce(true, fn x, acc -> fun.(x) and acc end)
end
all?
函数的对数是2(而不是3)
传递给reduce函数的初始值应为
答案 2 :(得分:-1)
第二个测试.... ListsRec5.all?(1..7,true,fn x-> x <8结尾)[]
我认为第二个测试应该返回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为true,则and还返回Expr2,否则,and也返回false,即Expr1为false时。
从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
。