A proper list is a list that ends in an empty list, such as:
[1, 2, 3] (which is syntactic sugar for [1 | [ 2 | [3 | [] ] ] ] )
An improper list is a list that does not end with an empty list. An example:
[1, 2 | 3] (which becomes [ 1 | [ 2 | 3 ] ] but cannot be rewritten further).
I’ve seen multiple resources (such as The wonderful Elixir in Action book and this question on StackOverflow) state that “many of the list-related functions do not work on them, but there are some cool things you can use them for.”
What cool things are hinted at? When are improper lists useful?
I don’t recall ever using it myself. I’d say it’s rarely called for. One example that comes to mind is saving a bit of memory. A pair represented as an improper list is smaller than with tuple:
So consequently, if you need to construct a bunch of pairs, you might save 1 word per pair. Note that for larger tuples (size >= 3) this won’t hold, and improper lists will in fact consume more memory.
Another example, which is mostly interesting in Erlang is simulating lazy lists (see here, the “Infinite Lists” example).
These are the only cases I can think of, so I’d say the usage is quite limited. I’d probably consider improper list only to save memory in some special cases, but I’d need very good reasons to go down that road. Since improper list could obscure the code, by default, I’d go for plain tuples.