I've been reading Erlang and OTP in action, and stumbled upon a question with regards to improper lists.
Don’t be tempted to use list cells
this way even if you think you have a
clever idea — it’s bug-prone and
confuses both humans and program
analysis tools. That said, there are
one or two valid uses for creating
improper lists, but they’re considered
advanced programming techniques and
are beyond the scope of this book.
Out of scope for the book? It must be perfect for Stackoverflow!
So my question is, of course, what would some valid uses would be?
One use suggested by Erlang documentation is faking lazy lists:
-module(lazy).
-export([ints_from/1]).
ints_from(N) ->
fun() ->
[N|ints_from(N+1)]
end.
One valid use is described at the very bottom of the Eunit user manual, in the section about lazy generators. This code example is supposed to create a very long list that will be consumed one element at a time, so instead of generating the entire list at once it creates an improper list whose tail describes how to generate the rest of the list:
lazy_test_() ->
lazy_gen(10000).
lazy_gen(N) ->
{generator,
fun () ->
if N > 0 ->
[?_test(...)
| lazy_gen(N-1)];
true ->
[]
end
end}.
In other words, it's a lazy list, which Erlang itself doesn't give you.
OTP stdlib dictionary implementation dict module is using improper lists for key-value pairs.
The justification is 2-tuple uses 1 word more memory than 2-element improper list. See
efficiency guide for details
OTP standard digraph module for directed graphs uses improper lists for tagged vertex and edge identifiers. For example, vertex 42 would be identified as ['$v'|42], which means a pair of an atom (no, not a character literal!) and an integer, similarly edge 97 would be ['$e'|97].