Enum filter changes list of numbers and nils to list of bytes

Background

I have a list of numbers that can contain nil entries:

iex(52)> test = [54, 54, 54, 56, nil, nil, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 57, 56, 56, 56, 56, 56]

[54, 54, 54, 56, nil, nil, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
 57, 57, 57, 57, 56, 57, 56, 56, 56, 56, 56]

Now, normally I would either use Enum.filter or Enum.reject to clean the nils out of it. Unfortunately, using it returns the following:

iex(53)> Enum.filter(test, fn n -> n != nil end )

'66688899999999999999999999999999999999999898888&&&&&&&&&&&&&&'

Same happens if I use is_nil instead of the custom condition.

Questions

  • Why is this happening?
  • How can I fix it?

You’re getting back a charlist: Binaries, strings, and charlists - The Elixir programming language

So you’re getting back the correct result but it’s printed differently

I assumed that much. My questions remain though, how can I avoid this? I absolutely want a list of numbers or integers.

They’re the same. It’s still a list of integers but iex displays it different.
You can do: IEx.configure(inspect: [charlists: :as_lists]) to have them printed as a list.

3 Likes

This is just how shell prints it. Try this:

iex(1)> [54,55,56] 
'678'
iex(2)> [54,55,56,1]
[54, 55, 56, 1]

Under the hood both printed representations are a linked list of integers, and the shell is trying to guess if the list is ascii-printable, and present at as something that “resembles” a human-readable string. There’s nothing to fix, but if you want it to be printed as a list of chars, use:

iex(3)> IO.inspect([54,55,56], charlists: :as_lists)    
[54, 55, 56]
iex(4)> :io.format("~w\n", [[54,55,56]])
[54,55,56]
3 Likes

They are a list of integers, you simply are seeing them printed which is what’s confusing people.

[48, 49, 50] and '012' are 100% exactly the same thing. The second one is just a different representation of the same 3-byte array.

iex can be configured to always show them as integer lists.

You can have a .iex.exs file at the root of your project and put this in it:

IEx.configure(charlists: :as_lists)

Open iex, try again, no more confusion.

1 Like