DEV Community

Ali Elshishini
Ali Elshishini

Posted on

Understanding Elixir's List.to_string

So I came across this (quite old) post on stackoverflow, someone wanted to print a list next to a string and he was struggling with it

16

I would like to print a list along with a string identifier like

list = [1, 2, 3]
IO.puts "list is ", list

This does not work. I have tried few variations like

# this prints only the list, not any strings
IO.inspect list
# using puts which also does

and I was a bit baffled as of why this is an issue at all, just convert your list to a string and print it, this logic should work in any language in any print function, should be simple and straightforward

Elixir surely have a function that convert a lists to string, and it does List.to_string

But to my surprise List.to_string was doing weird things

iex(42)> [232, 137, 178] |> List.to_string
<<195, 168, 194, 137, 194, 178>>
iex(43)> [1, 2, 3] |> List.to_string
<<1, 2, 3>>
Enter fullscreen mode Exit fullscreen mode

That was not what I was expecting, I was expecting a returned value that is similar to what IO.inspect produce

So to verify my expectation, I checked what clojure does, because clojure to me is the epitome of sanity

Clojure 1.12.4
user=> (str '(232 137 178))
"(232 137 178)"
user=> (str '(1 2 3))
"(1 2 3)"
Enter fullscreen mode Exit fullscreen mode

it was more or less what IO.inspect does
it returns something that look like how lists "look like" as code

So next step was more introspection

iex(47)> [232, 137, 178] |> List.to_string |> i
Term
  <<195, 168, 194, 137, 194, 178>>
Data type
  BitString
Byte size
  6
Description
  This is a string: a UTF-8 encoded binary. It's printed with the `<<>>`
  syntax (as opposed to double quotes) because it contains non-printable
  UTF-8 encoded code points (the first non-printable code point being
  `<<194, 137>>`).
Reference modules
  String, :binary
Implemented protocols
  Collectable, IEx.Info, Inspect, JSON.Encoder, List.Chars, String.Chars
Enter fullscreen mode Exit fullscreen mode

What the heck is BitString?

So I kept fiddling with the function, until I finally got it

iex(44)> ["o","m",["z","y"]] |> List.to_string
"omzy"
iex(45)> ["o","m",["z","y"]] |> IO.inspect
["o", "m", ["z", "y"]]
["o", "m", ["z", "y"]]
Enter fullscreen mode Exit fullscreen mode

List.to_string , does not transform a list to a string (preserving its structure), List.to_string flattens a list, take each element and transform it to a UTF-8 code point, and if you try to print that, you will get whatever string those codes points produce

iex(49)> [232, 137, 178] |> List.to_string |> IO.puts
è²
:ok
iex(50)> [91, 50, 51, 50, 44, 32, 49, 51, 55, 44, 32, 49, 55, 56, 93] |> List.to_string |> IO.puts
[232, 137, 178]
:ok
Enter fullscreen mode Exit fullscreen mode

In retrospect this is what the docs says



but well, the docs wasn't telling what I wanted it to say 😀

And oh, before I forget, Elixir have the inspect function, which does exactly was I thought List.to_string would do

iex(53)> [232, 137, 178] |> inspect |> IO.puts
[232, 137, 178]
:ok
iex(54)> ["o","m",["z","y"]] |> inspect |> IO.puts
["o", "m", ["z", "y"]]
:ok
Enter fullscreen mode Exit fullscreen mode

Top comments (0)