List of numbers sometimes displays as garbage (e.g., ~c"\a\t\n\f\r")

The problem with my code is that for x ← list, do: x+5 always returns garbage (e.g., ~c"\a\t\n\f\r"). It seems that all other values work correctly. I have tried this using a MacBook Pro M2 in VSCode and iex. I have tried this multiple times. Below are my tests and results.

iex(1)> list = [2,4,5,7,8]
[2, 4, 5, 7, 8]
iex(2)> for x <- list, do: x+2
[4, 6, 7, 9, 10]
iex(3)> for x <- list, do: x+3
[5, 7, 8, 10, 11]
iex(4)> for x <- list, do: x+4
[6, 8, 9, 11, 12]
iex(5)> for x <- list, do: x+5
~c"\a\t\n\f\r"
iex(6)> for x <- list, do: x+6
[8, 10, 11, 13, 14]
iex(7)> for x <- list, do: x+7
[9, 11, 12, 14, 15]

I’d really appreciate any guidance you can offer. Thanks!

3 Likes

FAQ: Why is my list of integers printed as a string? this might address your issue

3 Likes

What you are seeing (the “c” sigil ~c"…") is called a “charlist”. It’s a format used (more in Erlang than Elixir) to encode text: as unicode codepoints in a list.

What is happening is that the numbers you are displaying in a list ([7, 8, 9, 10, 11, 12]) happen to all be printable unicode codepoints. Elixir defaults to displaying these as charlists in case you were intentionally trying to handle unicode data encoded in this format. (The other lists contain numbers that are not printable unicode codepoints, but numbers that represent other non-printable characters like null characters and carriage returns, and so Elixir determines you must not be trying to display the list of numbers as text.)

In this instance, 7 happens to be printable as the unicode “bell noise” character \a, 8 is the tab character \t, etc.

Of course in Elixir, we normally use binary strings, not charlists, for textual data. If you are confident you won’t be using charlists to describe textual data (which is a safe assumption), you can prevent IEX from trying to display lists of numbers as charlists by creating a file called .iex.exs in the root of your project (or in your home directory to apply this to all projects) and instructing it to always inspect things that might be charlists as normal lists of numbers, even if they are all printable unicode codepoints:

# .iex.exs
IEx.configure(
  inspect: [
    charlists: :as_lists,
  ]
)

This will ensure your lists of arbitrary numbers are never interpreted (for display purposes) as textual data. Of course, the data is the same under the covers: [7, 8, 9, 10, 11, 12] = ~c"\a\t\n\f\r" are the same, and evaluate to the same list of numbers. But this will prevent IEX from making the assumption that there might be valuable unicode information in the list worth displaying to the programmer as text.

6 Likes

Thanks! That fixed it. I really appreciate your help!

2 Likes