Earlier quoted context omitted.
But 'def' doesn't have to work that way. Consider, in CL: > (defvar *fn* (let ((x 3)) (lambda (&optional (y (list nil x))) (push 7 (car y)) ; modifies the list y))) *FN* > (funcall *fn*) ((7) 3) > (funcall *fn*) ((7) 3) From this example you can see two things. First, the binding of 'x' is closed over when the lambda expression is evaluated. And second, the expression that provides the default value of 'y' is evaluat…
Expensive, though. http://stackoverflow.com/questions/1651154/why-are-default-a...
The code that evaluates the default expression doesn't need to be in a separate function, either, so the argument that calling that function is too expensive also doesn't hold water.
I just tried a test in SBCL:
(defun foo1 (x) x)
(defun test1 (n) (dotimes (i n) (foo1 (cons nil nil))))
(time (test1 100000000))
=> 4.4 sec, or 44ns / iteration
(defun foo2 (&optional (x (cons nil nil))) x)
(defun test2 (n) (dotimes (i n) (foo2)))
(time (test2 100000000))
=> 4.1 sec, or 41ns / iteration
The version with the optional parameter is actually slightly faster, which completely blows a hole in the performance argument.Look, no language is perfect -- not even Common Lisp :-) I think users are better served when design flaws in a language are acknowledged without defensiveness than when bogus justifications are offered.