Interlude: “Mistakes were made.”

As I was writing the next two études, I tried, despite the examples in the book, to avoid using lists:reverse/1. I thought, “Why can’t I add items to the end of a list using the cons (vertical bar; |) notation?” Here’s why.

I decided to do a simple task: take a list of numbers and return a list consisting of the squares of the numbers. I tried adding new items to the end of the list with this code:

-module(bad_code).
-export([squares/1]).

squares(Numbers) -> squares(Numbers, []).

squares([], Result) -> Result;

squares([H | T], Result) -> squares(T, [Result | H * H ]).

The resulting list was in the correct order, but it was an improper list.

1> c(bad_code).
{ok,bad_code}
2> bad_code:squares([9, 4.22, 5]).
[[[[]|81]|17.8084]|25]

That didn’t work. Wait a minute—the book said that the right hand side of the cons (|) operator should be a list. “OK, you want a list?” I thought. “I’ve got your list right here.” (See the last line of the code, where I wrap the new item in square brackets.)

squares2(Numbers) -> squares2(Numbers, []).

squares2([], Result) -> Result;

squares2([H | T], Result) -> squares2(T, [Result | [H * H] ]).

There. That should do the trick.

6> c(bad_code).
{ok,bad_code}
7> bad_code:squares2([9, 4.22, 5]).
[[[[],81],17.8084],25]

The result was better, but only slightly better. I didn’t have an improper list any more, but now I had a list of list of list of lists. I could fix the problem by changing one line to flatten the final result.

squares2([], ...

Get Études for Erlang now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.