Chapter 5
May 27, 2014
Common Lisp
##Optional Parameters
we can use optional arguments in a function, such as:
(defun foo (a b &optional c d)
(list a b c d))
This will result:
(foo 1 2) -> (1 2 NIL NIL)
(foo 1 2 3) -> (1 2 3 NIL)
(foo 1 2 3 4) -> (1 2 3 4)
Besides, we can set default value for a argument:
(defun foo (a &optional (b 10))
(list a b))
This will result:
(foo 1 2) -> (1 2)
(foo 1) -> (1 10)
In this example, argument b is set to 10 by default.
We can also know whether a value is set by default or by explicitly.
(defun foo (a b &optional (c 3 c-supplied-p))
(list a b c c-supplied-p))
For example:
(foo 1 2) -> (1 2 3 NIL)
(foo 1 2 3) -> (1 2 3 T)
(foo 1 2 4) -> (1 2 4 T)
Besides, we can use the value of argument which appears earlier in the argument list:
(defun foo (a &optional (b a))
(+ a b))
##Keyword Parameters
(defun foo (&key a b c)
(list a b c))
function can be invoked as follows:
(foo) -> (NIL NIL NIL)
(foo :a 1) -> (1 NIL NIL)
(foo :b 1) -> (NIL 1 NIL)
(foo :a 1 :c 3) -> (1 NIL 3)
Keyword parameters can provide a default value form and the name of a supplied-p value. e.g.:
(defun foo (&key (a 0) (b 0 b-supplied-p) (c (+ a b)))
(list a b c b-supplied-p))
If you want the keyword the caller uses to specify the parameter to be different from the name of the actual parameter. e.g:
(defun foo (&key ((:apple a)) ((:box b) 0) ((:charlie c) 0 c-supplied-p))
(list a b c c-supplied-p))
##Mixing Different Parameter Types
Combing &optional and &key parameters yields surprising results. e.g:
(defun foo (x &optional y &key z)
(list x y z))
It works like this:
(foo 1 2 :z 3) -> (1 2 3)
(foo 1) -> (1 nil nil)
(foo 1 :z 3) -> ERROR
In the last case, the keyword :z is taken as a value to fill the optional y parameter and leaving only the argument 3 to be processed. So it leads to ERROR.
However, we can combine &rest and &key parameters. e.g:
(defun foo (&rest rest &key a b c)
(list rest a b c))
you get this result:
(foo :a 1 :b 2 :c 3) -> ((:A 1 :B 2 :C 3) 1 2 3)