2015-08-31 13 views
7

Ich habe etwas Seltsames in Elixir mit String.to_integer. Nichts Wichtiges, aber ich würde gerne wissen, ob es eine Möglichkeit gibt, alle meine Funktionen mit dem Pipe-Operator zu verbinden.Seltsames Verhalten mit String.to_integer/1

Hier ist das Problem. Diese Codezeile (können Sie versuchen, in "iex"):

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.map_join "", &(Integer.to_string(&1)) 

gibt die Zeichenfolge "3765"

Was ich will, ist eine ganze Zahl. Also muss ich nur dieses kleine Stück Code |> String.to_integer am Ende der vorherigen Aussage hinzufügen, und ich sollte eine ganze Zahl haben. Lass es uns versuchen. Dieses Stück Code:

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.map_join "", &(Integer.to_string(&1)) 
|> String.to_integer 

gibt mir dies: "3765". Keine ganze Zahl, eine Zeichenkette!

Wenn ich das aber:

a = [5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.map_join "", &(Integer.to_string(&1)) 
String.to_integer(a) 

Es gibt mir eine ganze Zahl: 3765.

Es ist, was ich gerade mache, aber es macht mich wütend, weil ich würde lieben, alle diese Funktion die gute Art und Weise mit dem erstaunlichen Pfeifenbetreiber zu verketten.

Danke für die Hilfe oder die Lichter. Elixier macht sehr viel Spaß!

Antwort

9

Sie müssen Klammern um die Argumente zu map_join hinzufügen. Derzeit wird der Code interpretiert als

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.map_join("", &(Integer.to_string(&1) |> String.to_integer)) 

, was Sie wollen, ist allerdings

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.map_join("", &(Integer.to_string(&1))) 
|> String.to_integer 

Im Allgemeinen Sie immer Klammern verwenden müssen, wenn Sie Aufnahmen in einer Pipeline verwenden Mehrdeutigkeiten zu vermeiden. Die Erfassung kann auch auf &Integer.to_string/1 vereinfacht werden:

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.map_join("", &Integer.to_string/1) 
|> String.to_integer 

Aber ein einfaches Enum.join wird das gleiche tun. Wenn Sie the implementation betrachten, werden die Integer trotzdem in Strings umgewandelt, indem the String.Chars protocol verwendet wird.

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.join 
|> String.to_integer 

By the way, können Sie das gleiche erreichen, ohne Saiten überhaupt mit:

[5, 6, 7, 3] 
|> Enum.reverse 
|> Enum.reduce(0, &(&2 * 10 + &1)) 

Ach ja, und dann gibt es Integer.digits und Integer.undigits, die verwendet werden können, eine ganze Zahl zu konvertieren und aus eine Liste von Ziffern. Es ist nicht in der aktuellen Version vorhanden, obwohl es in der 1.1.0-dev Zweig ist, so dass ich vermute, dass es in 1.1.0 kommen wird. Sie können den Fortschritt beobachten here.

[5, 6, 7, 3] 
|> Enum.reverse 
|> Integer.undigits 
+2

diesem Grund habe ich im Allgemeinen gegen optional Pars bin. In ein paar Fällen ist es schön zu haben, aber ich denke, es ist im Allgemeinen besser, die Angewohnheit zu schaffen, immer Parens dort hinzustellen, wo sie gebraucht werden. – Davs

+0

@Patrick Oh Mann, es ist so hilfreich. Danke für die Erläuterung der Klammer und für die bessere und schönere Alternativlösung. Ich bin es still, wenn es Ihnen nichts ausmacht :-) – d34n5