IO.puts output

How am I to interpret the output here:

iex(5)> IO.puts [1, 2, 3]
^A^B^C
:ok

In Ruby, this is what I get:

2.4.0 :002> puts [1, 2, 3]
1
2
3
=> nil

Each element of the list is output followed by a newline.

Thanks.

TL;DR:
[1,2,3] is character list.

character list is inherited from Erlang and is internally represented as a list of integers

To display [1,2,3] you have to use:

IO.inspect [1,2,3], charlists: :as_lists
2 Likes

Run this in iex and it will explain it:

iex(1)> i [104, 105]

(You can replace the numbers with any printable unicode values for note)

1 Like

It put out the literal integer values 1, 2, 3, not the text representations, and your terminal shows them as control-a, control-b, control-c. This is because a list of integers is an old representation of a string.

What you probably wanted was IO.inspect

1 Like

No, I don’t want IO.inspect. What I want is to understand how the ascii code 1 gets translated by iex to ^A in my terminal window. For instance, this makes sense to me:

 iex(21)> IO.puts [97,98,99]
 abc

Is there some conversion chart for unprintable characters where the character code 1 is represented by ^A and the character code 2 is represented by ^B ?

Edit: Okay, I found it. Here is the rule:

Control characters are often rendered into a printable form known as caret notation by printing a caret (^) and then the ASCII character that has a value of the control character plus 64

And:

Caret notation is used in many programs, particularly Unix terminal drivers

I know some erlang, and Elixir’s charlists appear to be identical to erlang strings, and now that I try something similar in erlang, I see the same output(which I’ve never seen before):

$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V9.3  (abort with ^G)

1> io:format("~s~n", [[1,2,3]]).
^A^B^C
ok

In erlang, I’m used to seeing things like this:

5> [97,98,99].
"abc"

6> [0,97,98,99].
[0,97,98,99]

not the caret notation.

2 Likes

The carot notation is used to print unprintable characters.

In the repl as your example it prints it via ‘inspect’ (a similar thing for erlang), but when in an iolist context like IO.puts or io:format ~s then it is rendered like an IOList, thus a recursive sum type of lists of the sum type, or integers, or binaries. This means you can do things like print control characters to terminals or print out a binary blob or so forth. :slight_smile:

1 Like

This was already discussed here: Enum.filter BUG?!