让我们在Elixir中看到以下表达式:
iex> for n <- 1..30, rem(n, 3) == 0, do: n * 10
[30, 60, 90, 120, 150, 180, 210, 240, 270, 300]
Run Code Online (Sandbox Code Playgroud)
我尝试使用:into可选项来总结它们,但它失败了:
# 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
Run Code Online (Sandbox Code Playgroud)
是否可以使用:into组合枚举数值的结果?
如果有,怎么样?
不,into只能用于收集Collectable类型.整数不是Collectable.
你可以Enum.sum/1在这里使用,但你可能已经知道:
iex(1)> Enum.sum(for n <- 1..30, rem(n, 3) == 0, do: n * 10)
1650
Run Code Online (Sandbox Code Playgroud)
Enum.reduce/3但是,如果你的目标是不创建一个中间列表,你可以在这里使用:
Enum.reduce(1..30, 0, fn n, acc -> if(rem(n, 3) == 0, do: acc + n * 10, else: acc) end)
1650
Run Code Online (Sandbox Code Playgroud)
编辑:整数可以通过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
Run Code Online (Sandbox Code Playgroud)
输出:
1650
Run Code Online (Sandbox Code Playgroud)