This page contains the description of the following commands mapc, mapcan, mapcar, mapcon, maplist.
See map below
See map below
See map below
See map below
See map below
We describe here the eight functions map, mapc, mapcar, mapcan, mapcon, maplist, every, any. These function takes at least two arguments. The first argument is a function. It will be applied to arguments a1k, a2k, ..., ank, for k equals to 1, 2, 3, etc. In the general case, aik is the k-th element of the list argi (the i-th argument of map, with the convention that the function to apply is the 0-th argument). Exception: in the case of maplist, mapcon and map, the argument is aik is the list argi without its k-1 first elements.
Suppose that K is the minimum of the length of the arguments. Then K is the maximum number of function calls (this means that some part of the arguments will be unused, except for maplist, mapcon and map). Assume that the function returns v1, v2, v3, etc. The return value of any is the first non-nil vk; moreover execution stops when such a value is found. The return value is nil, if every function call gives nil. The return value of every is nil in case one vk is nil, moreover execution stops when such a value is found. The return value is vK otherwise (if all values are non-nil, the last one is returned). In the special case where one argument is empty, case where K is zero, the return value is true
For the six remaning functions, all K values are computed. The return value is the following: the functions map and mapc return nil. The functions maplist and mapcar return the list (v1 ... vK). The functions mapcon a and mapcan return the concatenation of the vi, obtained via nconc.
Let's start with defining some functions. Let's see also what happens in the case where the number of arguments is wrong.
[Endymion] (setq x (gensym)) g1 [Endymion] (setq lambda-0 (lambda () 0)) (#:system:lambda 0 () 0) [Endymion] (setq lambda-1 (lambda (x) (car x))) (#:system:lambda 1 (x) (car x)) [Endymion] (setq lambda-12 (lambda (x . y) (car x))) (#:system:lambda -2 (x . y) (car x)) [Endymion] (setq lambda-01 (lambda x (car (car x)))) (#:system:lambda -1 x (car (car x))) [Endymion] (setq lambda-3 (lambda (a b c) (if (equal a b) c))) (#:system:lambda 3 (a b c) (if (equal a b) c)) [Endymion] (mapc) (map) (maplist) (mapcon) (mapcar) (mapcan)(every)(any) mapc : wrong number of arguments : 0 this should be at least 2 map : wrong number of arguments : 0 this should be at least 2 maplist : wrong number of arguments : 0 this should be at least 2 mapcon : wrong number of arguments : 0 this should be at least 2 mapcar : wrong number of arguments : 0 this should be at least 2 mapcan : wrong number of arguments : 0 this should be at least 2 every : wrong number of arguments : 0 this should be at least 2 any : wrong number of arguments : 0 this should be at least 2
Let's try to map an undefined function or a function that takes no argument. Nothing interesting happens. Note that the number of arguments is checked exactly once. The `wrong number of arguments' message is issued by the evaluator, not the function.
[Endymion] (mapc x 0) mapc : undefined function : g1 [Endymion] (map x 0) map : undefined function : g1 [Endymion] (maplist x 0) maplist : undefined function : g1 [Endymion] (mapcon x 0) mapcon : undefined function : g1 [Endymion] (mapcar x 0) mapcar : undefined function : g1 [Endymion] (mapcan x 0) mapcan : undefined function : g1 [Endymion] (every x 0) every : undefined function : g1 [Endymion] (any x 0) any : undefined function : g1 [Endymion] (map 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (maplist 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (mapcon 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (mapcar 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (mapcan 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (every 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (any 'version ()) version : wrong number of arguments : 1 this should be 0 [Endymion] (mapcar lambda-0 ())) (#:system:lambda 0 () 0) : wrong number of arguments : 1 this should be 0)
Let's consider mapc. In order to show that the function is applied, we give invalid arguments.
[Endymion] (mapc 'car '((1) (2) (3))) () [Endymion] (mapc 'car '((1) (2) (3) 4)) car : not a list : 4 [Endymion] (mapc lambda-1 '((1) (2) (3))) () [Endymion] (mapc lambda-1 '((1) (2) (3) 4)) car : not a list : 4 [Endymion] (mapc lambda-01 '((1) (2) (3))) () [Endymion] (mapc lambda-01 '((1) (2) (3) 4)) car : not a list : 4 [Endymion] (mapc lambda-12 '((1) (2) (3))) () [Endymion] (mapc lambda-12 '((1) (2) (3) 4)) car : not a list : 4 [Endymion] (mapc lambda-12 '((1) (2) (3) 4) '(1 2 3)) () [Endymion] (mapc lambda-12 '((1) (2) (3) 4) '(1 2 3 4)) car : not a list : 4 [Endymion] (mapc 'cons '((1) (2) (3) 4) '(1 2 3 4)) () [Endymion] (mapc 'list '((1) (2) (3) 4) '(1 2 3 4)) () [Endymion] (mapc lambda-3 '((1) (2) (3) 4) '(1 2 3 4) ) (#:system:lambda 3 (a b c) (if (equal a b) c)) : wrong number of arguments : 2 this should be 3 [Endymion] (mapc lambda-3 '((1) (2) (3) 4) '(1 2 3 4) '(3 4)) () [Endymion] (mapc 'print '((1) (2) (3) 4) '(1 2 3 4) '(3 4)) (1)13 (2)24 ()
Consider now mapcar. It's like mapc, but the return value is the list of evaluations.
[Endymion] (mapcar 'car '((1) (2) (3) 4)) car : not a list : 4 [Endymion] (mapcar 'car '((1) (2) (3) (4))) (1 2 3 4) [Endymion] (mapcar lambda-1 '((1) (2) (3) (4))) (1 2 3 4) [Endymion] (mapcar lambda-01 '((1) (2) (3) (4))) (1 2 3 4) [Endymion] (mapcar lambda-12 '((1) (2) (3) (4))) (1 2 3 4) [Endymion] (mapcar lambda-12 '((1) (2) (3) (4)) '(1 2 3)) (1 2 3) [Endymion] (mapcar lambda-3 '((1) (2) (3) (4)) '(1 2 3) '(4 5 6)) (() () ()) [Endymion] (mapcar lambda-3 '((1) (2) (3) (4)) '(1 2 3) '(4 5 6)) (() () ()) [Endymion] (mapcar lambda-3 '((1) (2) (3) (4)) '(1 (2) 3) '(4 5 6 7)) (() 5 ()) [Endymion] (mapcar 'list '((1) (2) (3) (4)) '(1 (2) 3) '(4 5 6 7)) (((1) 1 4) ((2) (2) 5) ((3) 3 6))
Consider now every and any.
[Endymion] (every 'car ()) true [Endymion] (any 'car ()) () [Endymion] (every 'car '((1) (2) (3))) 3 [Endymion] (any 'car '((1) (2) (3))) 1 [Endymion] (every 'car '((1) 2 (3))) car : not a list : 2 [Endymion] (any 'car '((1) 2 (3))) 1 [Endymion] (every 'car '(() () ())) () [Endymion] (any 'car '(() () ())) () [Endymion] (every lambda-1 '((1) 2 (3))) car : not a list : 2 [Endymion] (every lambda-1 '((1) () 2 (3))) () [Endymion] (any lambda-1 '((1) () 2 (3))) 1 [Endymion] (any lambda-1 '(() (1) () 2 (3))) 1 [Endymion] (any lambda-1 '(() () () 2 (3))) car : not a list : 2 [Endymion] (every lambda-01 '((1) 2 (3))) car : not a list : 2 [Endymion] (every lambda-01 '((1) (2) (3))) 3 [Endymion] (every lambda-01 '((1) () 2 (3))) () [Endymion] (any lambda-01 '((1) () 2 (3))) 1 [Endymion] (any lambda-01 '(() () 2 (3))) car : not a list : 2 [Endymion] (any lambda-01 '(() () (2) (3))) 2 [Endymion] (every lambda-12 '((1) () 2 (3))) () [Endymion] (every lambda-12 '((1) (3))) 3 [Endymion] (any lambda-12 '((1) (3))) 1 [Endymion] (every lambda-12 '((1) () 2 (3)) '(1 2)) () [Endymion] (every lambda-12 '((1) () 2 (3)) '(1 2 3)) () [Endymion] (every lambda-12 '((1) (3) 2 (3)) '(1 2 3)) car : not a list : 2 [Endymion] (every lambda-12 '((1) (3) 2 (3)) '(1 2)) 3 [Endymion] (any lambda-12 '((1) () 2 (3)) '(1 2 3)) 1 [Endymion] (any lambda-12 '(() () 2 (3)) '(1 2 3)) car : not a list : 2 [Endymion] (any lambda-12 '(() () 2 (3)) '(1 2 )) () [Endymion] (any lambda-12 '(() () (2) (3)) '(1 2 3 )) 2 [Endymion] (every lambda-3 '((1) (3) 2 (3)) '(1 2) '(1 2 3 4)) () [Endymion] (any lambda-3 '((1) (3) 2 (3)) '(1 2) '(1 2 3 4)) () [Endymion] (every lambda-3 '((1) (3) 2 (3)) '((1) 2) '(1 2 3 4)) () [Endymion] (any lambda-3 '((1) (3) 2 (3)) '((1) 2) '(1 2 3 4)) 1 [Endymion] (every lambda-3 '((1) (3) 2 (3)) '((1) (3)) '(1 2 3 4)) 2 [Endymion] (any lambda-3 '((1) (3) 2 (3)) '((11) (3)) '(1 2 3 4)) 2 [Endymion] (every 'list '((1) (3) 2 (3)) '((11) (3)) '(1 2 3 4)) ((3) (3) 2) [Endymion] (any 'list '((1) (3) 2 (3)) '((11) (3)) '(1 2 3 4)) ((1) (11) 1)
We consider now map. It is the same as mapc, but is called on different things. In the same fashion maplist is the same as mapcar,
[Endymion] (map 'car '(1 2 3)) () [Endymion] (map (lambda (x) (print (car x))) '(1 2 3)) 1 2 3 () [Endymion] (map 'print '(1 2 3)) (1 2 3) (2 3) (3) () [Endymion] (map 'print '(1 2 3) '(4 5 6 7)) (1 2 3)(4 5 6 7) (2 3)(5 6 7) (3)(6 7) () [Endymion] (map 'print '(1 2 3) '(4 5 6 7) '(8 9)) (1 2 3)(4 5 6 7)(8 9) (2 3)(5 6 7)(9) () [Endymion] (map 'vset '(1 2 3) '(4 5 6 7) '(8 9)) vset : not a fixnum : (4 5 6 7) [Endymion] (maplist 'car '(1 2 3)) (1 2 3) [Endymion] (maplist lambda-01 '(1 2 3)) (1 2 3) [Endymion] (maplist lambda-12 '(1 2 3) '(4 5 6 7)) (1 2 3) [Endymion] (maplist lambda-12 '(1 2 3) '(4 5 6 7) '(8 9 10)) (1 2 3) [Endymion] (maplist 'list '(1 2 3) '(4 5 6 7) '(8 9 10)) (((1 2 3) (4 5 6 7) (8 9 10)) ((2 3) (5 6 7) (9 10)) ((3) (6 7) (10))) [Endymion] (maplist lambda-3 '(1 2 3 7) '(4 5 6 7) '(8 9 10 11)) (() () () (11)) [Endymion] (maplist lambda-3 '(1 2 6 7) '(4 5 6 7) '(8 9 10 11)) (() () (10 11) (11)) [Endymion] (maplist lambda-3 '(1 2 6 7) '(4 5 6 7) '(8 9 10 11 12)) (() () (10 11 12) (11 12))
We consider now mapcan and mapcon. Remember that results are appended by nconc. Thus, non-list are silentlty discrded.
[Endymion] (mapcon 'car '((1) (2) (3))) (1 2 3) [Endymion] (mapcan 'car '((1) (2) (3))) () [Endymion] (mapcan 'car '(((1)) ((2)) ((3)))) (1 2 3) [Endymion] (mapcon 'car '(((1)) ((2)) ((3)))) ((1) (2) (3)) [Endymion] (mapcon lambda-1 '(((1)) ((2)) ((3)))) ((1) (2) (3)) [Endymion] (mapcan lambda-1 '(((1)) ((2)) ((3)))) (1 2 3) [Endymion] (mapcan lambda-01 '(((1)) ((2)) ((3)))) (1 2 3) [Endymion] (mapcon lambda-01 '(((1)) ((2)) ((3)))) ((1) (2) (3)) [Endymion] (mapcan 'cons '(1 2 3) '(3 4 5 6)) (1 2 3) [Endymion] (mapcon 'cons '(1 2 3) '(3 4 5 6)) Quit
Session had to be interrupted: one of the list (guess which one) became circulat, hence of infinite length. Let's try again, being a bit more careful.
[Endymion] (defun g (x y) (cons (append x ()) (append y ()))) g [Endymion] (mapcon 'g '(1 2 3) '(3 4 5 6)) ((1 2 3) 3 4 5 6 (2 3) 4 5 6 (3) 5 6) [Endymion] (mapcan 'g '(1 2 3) '(3 4 5 6)) (() () ()) [Endymion] (mapcan 'list '(1 2 3) '(3 4 5 6) '(7 8)) (1 3 7 2 4 8) [Endymion] (mapcon 'list '(1 2 3) '(3 4 5 6) '(7 8)) ((1 2 3) (3 4 5 6) (7 8) (2 3) (4 5 6) (8))
The functions described above can be implemented in Lisp as follows.
(defun all-car (e) (if (null e) () (cons (caar e) (all-car (cdr e))))) (defun all-cdr (e) (if (null e) () (cons (cdar e) (all-cdr (cdr e))))) (defun all-ok (e) (if (null e) true (if (consp (car e)) (all-ok (cdr e)) ()))) (defun apply-cdr (f x y) (apply f (cons x (all-cdr y)))) (defun map (f . l) (when (all-ok l) (apply f l) (apply2 'map f l))) (defun mapc (f . l) (when (all-ok l) (apply f (all-car l)) (apply2 'mapc f l))) (defun maplist (f . l) (when (all-ok l) (cons (apply f l) (apply2 'maplist f l)))) (defun mapcar (f . l) (when (all-ok l) (cons (apply f (all-car l)) (apply2 'mapcar f l)))) (defun mapcon (f . l) (when (all-ok l) (nconc (apply f l) (apply2 'mapcon f l)))) (defun mapcan (f . l) (when (all-ok l) (nconc (apply f (all-car l)) (apply2 'mapcan f l)))) (defun every (f . l) (let ((res true)) (tagbody restart (if (not (all-ok l)) (go done)) (setq res (apply f (all-car l))) (setq l (all-cdr l)) (if res (go restart)) done) res)) (defun any (f . l) (let ((res ())) (tagbody restart (if (not (all-ok l)) (go done)) (setq res (apply f (all-car l))) (setq l (all-cdr l)) (if (not res) (go restart)) done) res))
back to home page © INRIA 2005, 2006 Last modified $Date: 2006/07/12 08:32:48 $