[comp.emacs] Mapping function documentation oversight?

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)