Espen Vestre <espen@vestre.net> wrote:
+---------------
| peder@news.klingenberg.no (Peder O. Klingenberg) writes:
| > That said, there's probably a reason why I couldn't immediately come
| > up with an example of a function (as opposed to AND) from my own code
| > that relies on the evaluation order of arguments.
|
| Defaults to keyword arguments are obvious candidates, and I thought I
| used defaults computed from the obligatory parameters all the time,
| but I actually only found one example in recent code.
+---------------
Oddly enough, I ran across a case of wanting to do exactly that just
last night, when writing a generalization for MAKE-LIST that allows
circular tails [yes, while playing around with the circular lists
mentioned in the "Subject: equal lists" thread] and is also capable
of initialing the elements of the list to a function of their position
[pardon the ugly draft code!]:
(defun make-list* (size &key initial-element
(circular-tail-size 0)
(initial-element-function
(constantly initial-element)))
(loop with prefix-length = (- size circular-tail-size)
and list = (make-list size)
and merge = nil
for i below size
and node on list
and last = nil then node
do (setf (car node) (funcall initial-element-function i))
when (= i prefix-length)
do (setf merge node)
finally (when (plusp circular-tail-size)
(setf (cdr last) merge))
(return list)))
The idea being that if you stick to MAKE-LIST args you get MAKE-LIST
semantics, but if not, well:
cmu> (make-list* 5)
(NIL NIL NIL NIL NIL)
cmu> (make-list* 5 :initial-element 'foo)
(FOO FOO FOO FOO FOO)
cmu> (make-list* 5 :initial-element-function #'identity)
(0 1 2 3 4)
cmu> (make-list* 5 :initial-element-function (lambda (x) (expt 2 x)))
(1 2 4 8 16)
cmu> (make-list* 5 :initial-element-function (lambda (x) (expt 2 x))
:circular-tail-size 3)
(1 2 . #1=(4 8 16 . #1#))
cmu>
Anyway, somewhere along the way I realized that if the
INITIAL-ELEMENT-FUNCTION argument were made to be the primary
source of initialization instead of INITIAL-ELEMENT [which,
as you'll see above is now used *only* by the default for
INITIAL-ELEMENT-FUNCTION], then by putting the keyword args in
the right order with the right defaults then "the right thing"
would simply happen automagically. ;-}
[But, no, off hand I can't think of any other code I've written
depending on the keyword arg order quite so strongly...]
-Rob
p.s. Can anyone think of better (shorter, mainly!) names for the
above args than INITIAL-ELEMENT-FUNCTION & CIRCULAR-TAIL-SIZE?
I tried INITIALIZATION-FUNCTION, but that didn't scan as well.
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607