让我们在Elixir中看到以下表达式:
iex> for n <- 1..30, rem(n, 3) == 0, do: n * 10
[30, 60, 90, 120, 150, 180, 210, 240, 270, 300]
我尝试使用:into
optional来总结它们,但它失败了:
# expect to get `1650` from `[30, 60, 90, 120, 150, 180, 210, 240, 270, 300]`
iex> for n <- 1..30, rem(n, 3) == 0, into: 0, do: n * 10
** (Protocol.UndefinedError) protocol Collectable not implemented for 0
(elixir) lib/collectable.ex:1: Collectable.impl_for!/1
(elixir) lib/collectable.ex:46: Collectable.into/1
是否可以使用:into
来合并枚举数字值的结果?
如果是,怎么样?
答案 0 :(得分:5)
不,into
只能用于收集Collectable
类型。整数不是Collectable
。
您可以在此处使用Enum.sum/1
,但您可能已经知道:
iex(1)> Enum.sum(for n <- 1..30, rem(n, 3) == 0, do: n * 10)
1650
如果您的目标是不创建中间列表,可以在此使用Enum.reduce/3
:
Enum.reduce(1..30, 0, fn n, acc -> if(rem(n, 3) == 0, do: acc + n * 10, else: acc) end)
1650
编辑:可以使用整数Collectable
来实现整数,但是我不推荐它,因为(1)这个实现是全局的,(2)没有明显的方法来“收集”变成一个整数,你也可以使用乘法而不是加法。仅出于学习目的,以下是如何为具有附加行为的整数实现Collectable
:
defimpl Collectable, for: Integer do
def into(acc) do
{acc, fn
acc, {:cont, x} -> acc + x
acc, _ -> acc
end}
end
end
IO.inspect for n <- 1..30, rem(n, 3) == 0, into: 0, do: n * 10
输出:
1650
答案 1 :(得分:1)
正如Dogbert所写,整数并没有实现Collectable协议。
如果您有任务:&#34;将列表转换为数字&#34;,请考虑Enum.reduce
。
a = for n <- 1..30, rem(n, 3) == 0, do: n * 10
Enum.reduce a, 0, &Kernel.+/2
> 1650