Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior with String.to_integer/1

Tags:

elixir

I have something strange in Elixir with String.to_integer. Nothing major, but I would like to know if there's a way to chain all my functions with the pipe operator.

Here is the problem. This line of code (you can try in "iex"):

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

returns the string "3765"

What I want is an integer. So I just have to add this little piece of code |> String.to_integer at the end the previous statement and I should have a integer. Let's try. This piece of code:

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

gives me this: "3765". Not an integer, a string!

If I do that though:

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

It returns me an integer: 3765.

It's what I'm doing right now but it makes me mad because I would love to chain all these function the good way with the amazing pipe operator.

Thanks for the help or the lights. Elixir is very fun!

like image 719
d34n5 Avatar asked Aug 31 '15 04:08

d34n5


Video Answer


1 Answers

You need to add parentheses around the arguments to map_join. Currently, your code is interpreted as

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

what you want is though

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

Generally, you always need to use parentheses when you are using captures inside a pipeline to avoid ambiguities. The capture can also be simplified to &Integer.to_string/1:

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

But a plain Enum.join will do the same thing. If you look at the implementation, it will convert the integers to strings anyway, using the String.Chars protocol.

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

By the way, you can achieve the same thing without using strings at all:

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

Oh, and then there's Integer.digits and Integer.undigits, which can be used to convert an Integer to and from a list of digits. It's not present in the current release, though it is in the 1.1.0-dev branch so I suspect it will come in 1.1.0. You can watch the progress here.

[5, 6, 7, 3] 
|> Enum.reverse 
|> Integer.undigits
like image 50
Patrick Oscity Avatar answered Oct 05 '22 15:10

Patrick Oscity