On Mon, 04 Jul 2011 20:11:56 +0300, Nikodemus Siivola wrote:
On 4 July 2011 19:42, Pascal J. Bourguignon pjb@informatimago.com wrote:
I don't think so.
I disagree strongly, and I'm pretty sure CLHS agrees with me, since it goes to the trouble of specifying what happens with FUNCALL.
CLHS, DEFINE-COMPILER-MACRO: "The &whole argument is bound to the form argument that is passed to the compiler macro function. The remaining lambda-list parameters are specified as if this form contained the function name in the car and the actual arguments in the cdr, but if the car of the actual form is the symbol funcall, then the destructuring of the arguments is actually performed using its cddr instead."
(I'm not really interested in fencing re. compiler-macros here, just trying to keep the record only moderately crooked. This is a sidetrack of epic proportions already: the OP asked about :KEY, not compiler-macros.)
I am very happy to learn about these things. Currently I am working on the algorithms and my main concern is to ensure correctness; speed is secondary at this point, but even though I am not optimizing, I want to keep my code optimizable later on.
My problem with the key argument is that it complicates the interface. I would like to use the same interface for sample statistics and random variables, eg currently in CL-NUM-UTILS and CL-RANDOM I have
(mean #(1d0 2d0 3d0)) ; => 2, a sample mean (mean (r-normal 2 1)) ; => 2d0, mean of a univariate normal distribution
If I had a :KEY argument, I would have to check that it is EQ to #'identity or not provided in methods for random variables.
APPLY is not a major concern for me at the moment, all of these functions have a fixed number of arguments (usually one or two). So compiler macros still look attractive: I guess I could just write them for the function I define (eg MAP1), with the understanding that if the user wants speed, he should stick to mapping with this function.
I also thought of the following possibility using runtime dispatch:
(defstruct (w/key (:constructor w/key (key object))) key object)
(defgeneric mean (object) (:method ((obj w/key)) (mean-w/key (w/key-object obj) (w/key-key obj))) (:method ((obj sequence)) (/ (reduce #'+ obj) (length obj))))
(defmethod mean-w/key ((obj sequence) key) (/ (reduce #'+ obj :key key) (length obj)))
(mean #(1 2 3)) ; => 2 (mean (w/key #'1+ #(1 2 3))) ; => 3
Tamas