Whats up with `[7,8]`?

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.

8 Likes

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.

3 Likes

Ah, I see now that @Ankhers was typing faster than me and already provided a great answer :slight_smile:

2 Likes
iex(1)> list = [7,8]
'\a\b'
iex(2)> IO.puts("#{inspect(list)}")
'\a\b'
:ok
iex(3)> IO.puts("#{inspect(list, [charlists: :as_charlists])}")
'\a\b'
:ok
iex(4)> IO.puts("#{inspect(list, [charlists: :as_list])}")
[7, 8]
:ok
iex(5)> 

Inspect.Opts

3 Likes