[7, 8, 9] in iex returns '\a\b\t' Why?

I just noticed this in Iex:

iex(1)> [1,2,3,4,5,6,7,8,9,10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
iex(2)> [7,8,9]
'\a\b\t'
iex(3)> [7]
'\a'
iex(4)> [6]
[6]
iex(5)> [6,7]
[6, 7]
iex(6)> [7,8]
'\a\b'

Why is this happening? :slight_smile:

1 Like

Hello and welcome,

it’s because they are the same thing…

a charlist is a list of char.

iex> [97, 98, 99]
'abc'
iex> [97, 98, 99, 0]
[97, 98, 99, 0]
iex> [97, 98, 99] == 'abc'
true
iex> Enum.map 'abc', & IO.inspect(&1)
97
98
99
'abc'

If it can, it will output char :slight_smile:

5 Likes

For information how to change this behaviour, see this previous answer: IEX - char printing - odd behavior

5 Likes

As other said, in addition You can use i/1 helper function in IEx session to get more informations about given type:

iex(1)> i [7,8,9]
Term
  '\a\b\t'
Data type
  List
Description
  This is a list of integers that is printed as a sequence of characters
  delimited by single quotes because all the integers in it represent printable
  ASCII characters. Conventionally, a list of Unicode code points is known as a
  charlist and a list of ASCII characters is a subset of it.
Raw representation
  [7, 8, 9]
Reference modules
  List
Implemented protocols
  Collectable, Enumerable, IEx.Info, Inspect, List.Chars, String.Chars
4 Likes

Elixir seems to be treating these as Charlists (scroll down a little in that)

I don’t know why it’s happening, but if I had to guess by looking at the ascii table, it’s because 0-6 are (I think) non-printable characters

Starting with 7, we have characters that are “printable” via escape codes. The most noticeable mappings you might recognize:

  • [9] maps to \t, which is a “tab” in ASCII
  • [10] maps to \n which is a new line
  • [13] maps to \r which is a carriage return

Why Elixir does this is unclear to me but it’s an interesting observation

Edit: A little more info

The description in the i helper function by @hauleth plus the explanation/link by @Nicd, coupled with the docs on info make sense to me now (it does a check to see if a character is printable or not). Leaving the info above in case it was useful

Because that’s the way Erlang represents strings. It makes interaction a lot easier when errors from Erlang are prettyprinted as charlists by default rather than as a list of strings.

2 Likes

It’s not really treating them differently, because they are charlists. As charlists are just lists of integers that represent characters, there is no way to differentiate them from “normal” lists. IEx is the one treating them differently when outputting them, as it tries to be friendly to you.

There is a similar thing with binaries, where strings are just binaries that contain UTF-8 data. IEx will print those binaries as strings. If there is data that is not valid UTF-8 or is not printable, it will print the bytes as numbers.

2 Likes

IEx is the one treating them differently when outputting them, as it tries to be friendly to you.

Thank you for this follow up. I didn’t read your previous link before I posted my response, but that made it much more clear. I’m going to use your suggestion in your other post (not to pretty print these) to configure my IEx

1 Like

There is a similar thing with binaries, where strings are just binaries that contain UTF-8 data

You know it’s really interesting that people freak out over [10] being ‘\n’ but few people would freak out over <<10>> being silently represented as “\n”. I wonder why.

Because the latter case is rarely seen.

Most play with lists in iex, not binaries.

And if they do, then they are probably already beyond that point.

2 Likes

Most languages have separate string and list datatypes and most of them don’t distinguish between single and double quotes, as both represent the same kind of string. Therefore it’s strange that a list might suddently become a “string”. <<10>> = "\n" on the other hand are both “strings” therefore the same datatype; no sudden “switch” of type.

1 Like

This confusion is why I’m still hoping we can make this a reality some day: Replace 'charlist' by ~c[charlist] in your own codebases

2 Likes