Exercises
Exercise 2.21
The function square-list/1
takes a list of numbers as argument and returns a list of the squares of those numbers.
> (square-list (list 1 2 3 4))
(1 4 9 16)
Here are two different definitions of square-list/1
. Complete both of them by filling in the missing expressions:
(defun square-list
(('()) '())
((items) (cons <??> <??>)))
(defun square-list (items)
(map <??> <??>))
Exercise 2.22
Louis Reasoner tries to rewrite the first square-list function of exercise 2.21 so that it evolves an iterative process:
(defun square-list (items)
(square-list items '()))
(defun square-list
(('() answer) answer)
(((cons head tail) answer)
(square-list tail
(cons (square head)
answer))))
Unfortunately, defining square-list
this way produces the answer list in the reverse order of the one desired. Why?
Louis then tries to fix his bug by interchanging the arguments to cons:
(defun square-list (items)
(square-list items '()))
(defun square-list
(('() answer) answer)
(((cons head tail) answer)
(square-list tail
(cons answer
(square head)))))
This doesn't work either. Explain.
Exercise 2.23
The built-in LFE function lists:foreach/2
is similar to our mapper/2
and the built-in lists:map/2
. It takes as arguments a function and a list of elements. However, rather than forming a list of the results, foreach/2
just applies the function to each of the elements in turn, from left to right. The values returned by applying the function to the elements are not used at all -- foreach/2
is used with functions that perform an action, such as printing. For example,
> (lists:foreach (lambda (x) (io:format "~n~p~n" (list x)))
(list 57 321 88))
57
321
88
The value returned by the call to foreach/2
(not illustrated above) can be something arbitrary, such as true
. Give an implementation of foreach/2
that mimics the behaviour of the built-in function.