squash@MATH.UFL.EDU (Jonathan King) (01/13/91)
Node (elisp)Mapping Functions of *info* gives this example of using mapping functions, to define a more complex mapping function `mapcar*' : (defun mapcar* (f &rest args) "Apply FUNCTION to successive cars of all ARGS, until one ends. Return the list of results." (cons (apply f (mapcar 'car args)) ; Apply function to CARs. (let ((rest (mapcar 'cdr args))) (if (not (memq 'nil rest)) ; If no list is exhausted, (apply 'mapcar* f rest))))) ; recurse for rest of elements. (mapcar* 'cons '(a b c) '(1 2 3 4)) => ((a . 1) (b . 2) (c . 3)) This works, but not in the base case where one or more of the ARGS is nil. Perhaps this version is acceptable: (defun mapcar* (f &rest args) "Apply FUNCTION to successive cars of all ARGS, until one ends. Return the list of results." (if (not(memq 'nil args)) ; If no list is exhausted, (cons (apply f (mapcar 'car args)) ; Apply function to CARs. (apply 'mapcar* f (mapcar 'cdr args)) ; Recurse for rest of elements. ))) Jonathan PS> I would like to be able to say that I simply read the description of mapcar* and saw the problem. However, I am trying to learn how to use mapping function. I copied mapcar* and used in a larger program and got bitten by the base case... ================ PPS> I would appreciate comments of the form "Does/doesn't work." "Can be more efficient." on the following mapping function (which is written as a learning exercise, for me.) (defun mapcar+ (f &rest args) "Apply FUNCTION to successive cars of all non-nil ARGS, discarding elements of ARGS as they become exhausted. Returns the list of results. Warning: It is best that FUNCTION accept a variable number of arguments and be symmetric in those arguments." (setq args (delq nil args)) (if args ; If arguments are left (cons (apply f (mapcar 'car args)) ; apply function to CARs. (apply 'mapcar+ f (mapcar 'cdr args)) ; Recurse for rest of elements. ))) If FUNCTION does not alter its argument(s), can I conclude that mapcar+ is safe to ARGS since they are first bound up in a list? Here is an example in lisp-interaction-mode : (setq lis '(100 -3 200)) (100 -3 200) (mapcar+ '+ lis '(10 2 300) '(0 10 2 3 4) nil ) (110 9 502 3 4) lis (100 -3 200) (mapcar+ '+ ) nil (mapcar+ '+ nil nil) nil ;;; Now a destructive function, `sort': (defun sort_ (&rest numbers) (sort numbers '<) ) sort_ lis (100 -3 200) (mapcar+ 'sort_ lis '(10 2 300) '(0 10 2 3 4) nil ) ((0 10 100) (-3 2 10) (2 200 300) (3) (4)) lis (100 -3 200)