Tamas Papp tkpapp@gmail.com writes:
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
If that complicates the interface then don't use them!
&KEY are designed to simplify the interface. If that doesn't work in your case, don't use it.
(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.
Or you can just call the key in all cases.
(mean #(1 2 3)) ; => 2 (mean (w/key #'1+ #(1 2 3))) ; => 3
This will never be faster than keys.
Some compilers (such as sbcl), generate different entry points for functions with &key parameters, so that depending on the lexical keys specified at the call point, it can jump directly to the right parameter processing code.
Basically, the compiler behaves like if it generated automatically for:
(defun f (a &key k1 k2) ...)
the following code:
(defun f-0 (a) (let ((k1) (k2)) ...)) (defun f-k1 (a k1) (let ((k2)) ...)) (defun f-k2 (a k2) (let ((k1)) ...)) (defun f-k1-k2 (a k1 k2) ...) (defun f (a &rest r) (let ((k1 (get-key :k1 r)) (k2 (get-key k2 r))) ...))
;; only smarter, it avoids duplicating the ... code.
and when you call:
(f 42 :k1 11)
it generates:
(f1-k1 42 11)
So what you would do by hand could be done by the compiler.
Only if you called (apply 'f 42 keys) or (f 42 some-key 33) would it call the complex parameter processing entry point.