Elixir lists interpreted as char lists

ListElixir

List Problem Overview


I'm just starting out with Elixir. I'm writing some tests using ExUnit for simple Enumerable functions that I am implementing myself, without using the standard Enum module.

In my tests I'm finding that whenever I reference the list [7, 8, 9], once it is printed in in stdout I am seeing the char list '\a\b\t'. Why does this sort of thing happen?

List Solutions


Solution 1 - List

Elixir has two kinds of strings: binaries (double quoted) and character lists (single quoted). The latter variant is inherited from Erlang and is internally represented as a list of integers, which map to the codepoints of the string.

When you use functions like inspect and IO.inspect, Elixir tries to be smart and format a list of integers as a string for easy readability. However, in some cases you end up with a nonsense string just because all of the integers in your list happen to be valid codepoints. For example, the characters A through Z are represented as the integers 65 through 90 in ASCII.

iex> IO.inspect [65, 66, 67]
'ABC'

If you like to print a raw list, you can use the charlists: :as_lists option. For a full list of options fire up iex and type h Inspect.Opts.

iex> IO.inspect [65, 66, 67], charlists: :as_lists
[65, 66, 67]

With Elixir < 1.4, you can use char_lists: false.

By the way, this is not the only case where Elixir hides the underlying building blocks from you, it also happens with binaries (double quoted strings) and structs.

The deeper reason for this is that Elixir and Erlang do not have user-defined types, so there's no way to distinguish between a list and a single quoted string, because both are just lists. However, this can also be a strength in other situations. For example, it allows us to trivially serialize any data structure in Elixir and Erlang, because it can only be built from the basic building blocks that come with the language.

Solution 2 - List

While @Patrick's answer is absolutely correct, you can also configure IEx to always display charlists as regular lists instead of manually calling inspect every single time:

iex> IEx.configure(inspect: [charlists: :as_lists])
# => :ok

iex> [65, 66, 67]
# => [65, 66, 67]

iex> 'ABC'
# => [65, 66, 67]

Here's a full list of supported options.

You can also put this line in ~/.iex.exs in your home path, so the configuration is applied for every IEx session on your system.

Solution 3 - List

To disable this behaviour for your environment, create a ~/.iex.exs file to always apply the configuration:

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

This prevents the need to provide the option to inspect or to run IEx.configure manually each time.

You can also have separate .iex scripts per directory, if you want to override the global setting for a specific project.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorge TaverasView Question on Stackoverflow
Solution 1 - ListPatrick OscityView Answer on Stackoverflow
Solution 2 - ListSheharyarView Answer on Stackoverflow
Solution 3 - ListAdam MillerchipView Answer on Stackoverflow