Subject: Re: Making structures useable
From: rpw3@rpw3.org (Rob Warnock)
Date: Tue, 31 Aug 2004 08:14:33 -0500
Newsgroups: comp.lang.lisp
Message-ID: <urGdnXWT1N8k5KncRVn-uQ@speakeasy.net>
Tord Kallqvist Romstad  <romstad@math.uio.no> wrote:
+---------------
| rpw3@rpw3.org (Rob Warnock) writes:
| > Rather, what we really need is for implementors to add the :MAX-ARGS
| > keyword as an extension to REDUCE so that it can act like the Unix
| > shell command "xargs", that is, allow things like this:
| > 
| >     (REDUCE #'+ VALUES :MAX-ARGS 35)
| > 
| > which would internally APPLY the function argument successively
| > to length 34 (to account for the accumulated intermediate result)
| > subsequences of the sequence arg.
| 
| I don't see how you can make something like this work.  The value of
| (REDUCE FUNCTION ARGLIST) is in general not equal to the value of
| (APPLY FUNCTION ARGLIST).  As a trivial example, consider the
| following:
| 
| CL-USER> (defun average (&rest numbers)
| 	   (/ (reduce #'+ numbers)
| 	      (length numbers)))
| AVERAGE
| CL-USER> (apply #'average '(1.0 2.0 3.0))
| 2.0
| CL-USER> (reduce #'average '(1.0 2.0 3.0))
| 2.25
| 
| As far as I can see, your idea would only work if the implementation
| had some way of determining whether an n-ary function is
| left-associative.  This seems very hard to do.
+---------------

You took the idea out of context. The idea was to use it in the
*definition* of AVERAGE, where you *do* know that #'+ is associative:

         (defun average (&rest numbers)
  	   (/ (reduce #'+ numbers :max-args 50)
  	      (length numbers)))

But there's no point in that, since with a &REST arg you're already
limited by CALL-ARGUMENTS-LIMIT, so you might as well just define
AVERAGE as:

         (defun average (&rest numbers)
  	   (/ (apply #'+ numbers)
  	      (length numbers)))

Instead, where it really shines is in a LIST-AVERAGE, with a
calling sequence allowing more elements than CALL-ARGUMENTS-LIMIT:

         (defun list-average (list-of-numbers)
  	   (/ (reduce #'+ list-of-numbers :max-args call-arguments-limit)
  	      (length list-of-numbers)))

You'd get to pass in more than CALL-ARGUMENTS-LIMIT args, but you
wouldn't have to pay the overhead of calling #'+ once for every arg.


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607