Reputation: 11
When passing the string "word", I'm trying to print "W-oo-rrr-dddd" (it's a kata).
String.graphemes(word) |> Enum.with_index(1) |> Enum.reduce(
fn
({a, 1}, _) -> String.capitalize(a)
({a, i}, acc) -> acc <> "-" <> String.pad_trailing(String.capitalize(a), i, String.downcase(a))
end
)
But I get:
** (ArgumentError) argument error
lib/katas.ex:12: anonymous fn/2 in Katas.accum/1
(elixir) lib/enum.ex:1755: Enum."-reduce/2-lists^foldl/2-0-"/3
lib/katas.ex:9: Katas.accum/1
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/code.ex:170: Code.eval_string/3
However, if I take the accumulator concatenation out of the second function match, the error is not raised (although the code now is wrong)
String.graphemes("word") |> Enum.with_index(1) |> Enum.reduce(
fn
({a, 1}, _) -> String.capitalize(a)
({a, i}, _) -> String.pad_trailing(String.capitalize(a), i, String.downcase(a))
end
)
However, string concatenation seems to be working just fine:
iex(73)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> acc <> "-" <> x end)
"StringA-StringB"
So, how can I make the first piece of code work? Thanks
Upvotes: 1
Views: 1032
Reputation: 222188
You need to specify the initial value of the accumulator to ""
, otherwise it's set to the first item of the list, which means your accumulator starts off with a tuple {"w", 1}
, and you get the argument error when you try to use it as a string.
word = "word"
String.graphemes(word) |> Enum.with_index(1) |> Enum.reduce(
"",
fn
({a, 1}, _) -> String.capitalize(a)
({a, i}, acc) -> acc <> "-" <> String.pad_trailing(String.capitalize(a), i, String.downcase(a))
end
)
|> IO.inspect
Output:
"W-Oo-Rrr-Dddd"
I'd also suggest using Enum.map_join/3
here for more elegant (IMO) code:
word = "word"
String.graphemes(word)
|> Enum.with_index(1)
|> Enum.map_join(
"-",
fn
{a, 1} -> String.capitalize(a)
{a, i} -> String.pad_trailing(String.capitalize(a), i, String.downcase(a))
end
)
|> IO.inspect
Upvotes: 1