# Is this a bug, [H | T]?

In iex, [H|T] is judged as List, I think this is not right. I use Elixir 1.6.

Do you think so?

Thanks.

Nope, not a bug. Thatâ€™s called an improper list.

Hereâ€™s an existing thread about it. What can you do with improper lists?

``````iex(23)> x = [H|T]
[H | T]
iex(24)> is_list x
true
iex(25)> length x
BUG!!!** (ArgumentError) argument error
:erlang.length([H | T])
``````

Lists in erlang/elixir are linked lists, so `[1, 2, 3, 4, 5, 6]` is syntax sugar for `[1 | [2 | [3 | [4 | [5 | [6 | [] ] ] ] ] ] ]`, where each element contains a value and a pointer to a continuation. As long as the continuation links to another list the list is considered â€śproperâ€ť, while if it points to something else itâ€™s â€śimproperâ€ť. Proper lists are what you normally consider a list of values, but e.g. iodata uses improper lists to be able to combine many binary values to a single textual representation without falling into the performance issues of large binary concatination.

1 Like

Quick example of an improper list vs proper list:

``````# proper list
[ 1 | [ 2 | [] ] ]

# inproper list
[ 1 | 2 ]
``````

The `[]` at the end of a proper list is used by erlang to determine the end of a list. So functions like `length` will count the number of elements in a list until it reaches a `[]`. If that final element is missing we call it an `improper` list.

Incase your wondering what happens if an element in your list is an empty list like: `[ [], 1 ]`. Remember as @LostKobrakai said above that what we see is shorthand for `[ [] | [ 1 | [] ] ]` . As such empty lists that are elements wonâ€™t cause any trouble

`[1]` ist equivalent to `[1|[]]` and both are propper lists.

Thanks for pointing that out, Iâ€™ve included extra elements to correct my syntax.

If you look at the types, youâ€™ll see that itâ€™s not a bug in that case either. Here, the type of the parameter for `length/1` is `list`. If you look at some of the basic types supported here, youâ€™ll see `maybe_improper_list`, `nonempty_improper_list`, and `nonempty_maybe_improper_list`, which would be the types you want to use for improper lists. Elixir doesnâ€™t check the types for you, though. Youâ€™d need to use dialyzer, but dialyzer should complain if you had this code:

``````length([H | T])
``````
2 Likes