Elixir ArgumentError в Enum.reduce с конкатенацией строк

При передаче строки "слово" я пытаюсь напечатать "W-oo-rrr-dddd" (это ката).

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
)

Но я получаю:

** (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

Однако, если я извлекаю конкатенацию аккумуляторов из совпадения второй функции, ошибка не возникает (хотя код теперь неверен)

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
)

Тем не менее, конкатенация строк работает нормально:

iex(73)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> acc <> "-" <> x end)
"StringA-StringB"

Итак, как я могу заставить работать первый кусок кода? Спасибо

1 ответ

Вам необходимо указать начальное значение аккумулятора для ""в противном случае он устанавливается на первый элемент списка, что означает, что ваш аккумулятор начинается с кортежа {"w", 1}, и вы получаете ошибку аргумента, когда пытаетесь использовать его как строку.

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

Выход:

"W-Oo-Rrr-Dddd"

Я бы также предложил использовать Enum.map_join/3 здесь для более элегантного (IMO) кода:

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
Другие вопросы по тегам