Lisp has special types of functions that transform and expand
the meaning of other functions. The most common of these is
mapcar. Consider
(mapcar 'f 'list1 'list2 ... 'listn)
where f is a function and
list1, list2, ..., listn
are lists.
The result of this is to make up a new list that looks like:
( (f (car 'list1) (car 'list2) ... (car 'listn)
(f (cadr 'list1) (cadr 'list2) ... (cadr 'listn)
(f (caddr 'list1) (caddr 'list2) ... (caddr 'listn)
...
(f (last 'list1) (last 'list2) ... (last 'listn)) )
Thus
> (mapcar '1+ '(1 3 5 7))
(2 4 6 8)
> (mapcar '+ '(2 4 6 8) '(10 30 50 70))
(12 34 56 78)
> mapcar 'equal '(3 "egg" (a b) 47 (b (d)) 'neal 3.14)
'(4 "egg" (a c) 47 (b (d)) 'neal 3.14159))
(NIL T NIL T T T NIL)
;;;;;; which is:(NIL T NIL T T T NIL)
Similarly, (apply 'f '(s1 s2 ... sn)) becomes
(f 's1 's2 ... 'sn)
so that one has:
> (apply '+ '(2 4 6 8))
20
> (apply '* '(1 2 3 4 5))
120
> (apply 'list '(a b c d))
(A B C D)
- Give the result of each of the following:
> (mapcar '1+ '(1 2 3))
> (mapcar '+ '(1 2 3) '(8 10 12))
> (mapcar '* '(1 2 3) '(8 10 12))
> (mapcar 'car '((a b c) (x y z) (r s t)))
> (mapcar 'cdr '((a b c) (x y z) (r s t)))
> (apply '+ '(2 4 6 8))
> (apply '* '(1 2 3 4 5))
> (apply 'list '(a b c d))
- Use mapcar to define addvec above.
- Use mapcar to define vecmul above.
- Conclude that you can define innprod by
(defun innprod (x y)
(apply '+ (mapcar '* x y)) )
- Explain how each of the following functions work:
(defun countatoms2 (s)
(cond ((null s) 0)
((atom s) 1)
(t (apply '+ (mapcar 'countatoms2 s))) ))
(defun listatoms2 (s) ;; see text page 138
(cond ((null s) nil)
((atom s) (list s))
(t (apply 'append (mapcar 'listatoms2 s))) ))
(defun depth1 (s)
(cond ((null s) 1)
((atom s) 0)
(t (1+ (apply 'max (mapcar 'depth1 s)))) ))
- Check out the following transpose function
for matrices. This code shows some of the real power of
Lisp and of functional programming. A transpose function in
a traditional language is much more complicated.
> (defun transpose (l)
(cond ((null (car l)) nil)
(t (cons (mapcar 'car l) (transpose (mapcar 'cdr l)))) ))
TRANSPOSE
> (transpose '((a b c) (d e f) (g h i))) ;; 3-by-3
((A D G) (B E H) (C F I))
> (transpose '((A D G) (B E H) (C F I)))
((A B C) (D E F) (G H I))
> (transpose (transpose '((a b c) (d e f) (g h i))))
((A B C) (D E F) (G H I))
> (transpose '((b11 b12) (b21 b22) (b31 b32) (b41 b42) (b51 b52))) ;; 5-by-2
((B11 B21 B31 B41 B51) (B12 B22 B32 B42 B52))
> (transpose '((b11 b21 b31 b41 b51) (b11 b22 b32 b42 b52))) ;; 2-by-5
((B11 B11) (B21 B22) (B31 B32) (B41 B42) (B51 B52))
> (transpose (transpose '((b11 b12) (b21 b22) (b31 b32) (b41 b42) (b51 b52))))
((B11 B12) (B21 B22) (B31 B32) (B41 B42) (B51 B52))
The following code shows in more detail how this works:
.txt,
.pdf,
.ps.
In the code above, first a more traditional approach to
transpose in Lisp is shown, and the parts of the traditional
approach is step-by-step replaced by the use of mapcar.