I was playing around with Flow/GenStage and had a producer emitting integers, pushing through the official GenStage RateLimitier example. And then something really weird happened:
[1, 2]
[3, 4]
[5, 6]
'\a\b'
'\t\n'
What is going on here? Why is [7,8] printed as '\a\b'?
charlists. In Erlang, a string is a list of integers. So when Elixir sees that, and the integers are printable as characters, it doesn’t really know if it is meant to be a list of integers, or an Erlang string (charlist).
Edit
iex(1)> [104, 101, 108, 108, 111] == 'hello'
true
Some quick terminology.
Elixir charlist is the same as Erlang string.
Elixir string is the same as Erlang binary.
In Elixir if you want a charlist, you wrap your value in single quotes, 'hello'.
In Elixir if you want a binary, you wrap your value in double quotes, "hello".
iex(2)> "hello" == 'hello'
false
Note that they are different values.
Edit 2
Just because things can get confusing when you switch between Elixir and Erlang.
Just a recap for the Elixir syntax, :"hello" and :hello are atoms, 'hello' is a charlist and "hello" is a binary.
In Erlang, hello and 'hello' are atoms, "hello" is an Erlang string, and <<"hello">> is binary.
In the above examples, the single quotes around Erlangs 'hello' and the double quotes in Elixir’s :"hello" are not necessary. They are only required if you have an atom that has certain characters in the name.
that’s because charlists in Elixir are just, literally, lists of Unicode code points represented as integers. Therefore, if a list of integers contains only numbers corresponding to printable characters, Elixir console prints them as a charlist.
That does not mean that Elixir is changing it: [7, 8] and '\a\b' are effectively the same thing.