I am trying to understand the protocol aspect of Elixir better, and stumbled upon something I do not quite get about the interplay between Enumerable
and Collectable
. The Enum.into/2
function utilizes the Collectable
protocol for its second argument. Since a string is reported as implementing the Collectable
protocol by IEx, I would expect the following to be an identity:
"hello"
|> String.to_charlist()
|> Enum.into("")
However, this does not work as I expect (using Elixir 1.12). Instead I get a rather cryptic error message, at least to me:
** (FunctionClauseError) no function clause matching in anonymous fn/2 in Collectable.BitString.into/1
The following arguments were given to anonymous fn/2 in Collectable.BitString.into/1:
# 1
[""]
# 2
{:cont, 104}
(elixir 1.12.0) anonymous fn/2 in Collectable.BitString.into/1
(elixir 1.12.0) lib/enum.ex:2356: Enum."-into/4-lists^foldl/2-0-"/3
(elixir 1.12.0) lib/enum.ex:2356: Enum.into/4
If I instead use the following pipeline, I get the identity as expected:
"hello"
|> String.to_charlist()
|> List.to_string()
What am I missing? I get that the latter works, but would still like to understand the former.
Thanks in advance!