<jonrock@gmail.com> wrote:
+---------------
| I would like to find the entry in a list that maximizes a function.
| I started out with this:
|    (defun find-maximizing-item (lst fun)
|      (loop for item in lst
|            maximizing (funcall fun item)))
| but that returns only the maximum value of the function and nothing
| about what entry in the list made that maximum value happen.
| Is there some other idiom I should be using instead?
+---------------
I don't know of one. AFAIK, one has to do it "manually", e.g.:
    (defun find-maximizing-item (list &optional (function #'identity)
				      &key (test #'<))
      (let ((max-item (first list))
	    (max-value (funcall function (first list)))
	    (max-position 0))
	(loop for item in (rest list)
	      and position from 1
	      for value = (funcall function item)
	  when (funcall test max-value value)
	    do (setf max-item item
		     max-value value
		     max-position position))
	(values max-item max-value max-position)))
I added MAX-POSITION 'cuz it might be useful sometimes
[but made it be the last value in the result, in case
you don't care]; uncrunched the Schemish variable names;
made the FUNCTION optional; added TEST [just for fun];
and unrolled the loop once to avoid calling FUNCTION
twice on the first item.  Testing:
    > (find-maximizing-item '(3 -4 2 5 -7 1 2))
    5
    5
    3
    > (find-maximizing-item '(3 -4 2 5 -7 1 2) (lambda (x) (* x x)))
    -7
    49
    4
    > 
To make it more like other CL functions, you might want to make
the calling sequence use keyword KEY instead of a positional FUNCTION,
that is:
    (defun find-maximizing-item (list &key (key #'identity) (test #'<))
      (let ((max-item (first list))
	    (max-value (funcall key (first list)))
	    (max-position 0))
	(loop for item in (rest list)
	      and position from 1
	      for value = (funcall key item)
	  when (funcall test max-value value)
	    do (setf max-item item
		     max-value value
		     max-position position))
	(values max-item max-value max-position)))
    > (find-maximizing-item '(3 -4 2 5 -7 1 2) :key (lambda (x) (* x x)))
    -7
    49
    4
    > 
-Rob
p.s. I used #'< as the default :TEST [even though MAX-VALUE isn't an
input constant], because CLHS 17.2.1 "Satisfying a Two-Argument Test"
requires the list item being scanned to be the second argument of the
:TEST function.
-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607