2017-06-27 4 views
1

Wenn ich die Zeichenfolge "Wort" übergeben, versuche ich "W-oo-rrr-dddd" (es ist eine Kata) zu drucken.Elixir ArgumentError in Enum.Reduce mit String Verkettung

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 
) 

Aber ich bekomme:

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

Allerdings, wenn ich den Akku Verkettung nehmen aus der zweiten Funktion übereinstimmen, wird der Fehler nicht erhöht (obwohl der Code nun falsch ist)

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 
) 

Allerdings scheint String Verkettung gut zu funktionieren:

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

Also, wie kann ich das erste Stück Code arbeiten lassen? Dank

+0

Es scheint so, dass die 'String.capitalize/1 'verursacht Probleme in Ihrem reduzieren Fn (nicht sicher warum). Wenn Sie das entfernen und als 'String.pad_trailing (a, i, a)' behalten, funktioniert es gut (getestet in 1.4.4). Könntest du das geben? – matov

Antwort

1

Sie müssen den Anfangswert des Akkumulators "" angeben, sonst wird es auf das erste Element der Liste gesetzt, was bedeutet, dass Ihr Akkumulator mit einem Tupel beginnt {"w", 1}, und Sie erhalten das Argument Fehler auf, wenn Sie versuchen, um es als eine Zeichenfolge zu verwenden.

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 

Ausgang:

"W-Oo-Rrr-Dddd" 

Ich würde auch Enum.map_join/3 hier für elegantere (IMO) Code vorschlagen, mit:

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