views:

112

answers:

2

At the moment I'm working through "Practical Common Lisp" from Peter Seibel.

In the chapter "Practical: A Simple Database" (http://www.gigamonkeys.com/book/practical-a-simple-database.html) Seibel explains keyword parameters and the usage of a supplied-parameter with the following example:

(defun foo (&key a (b 20) (c 30 c-p)) (list a b c c-p))

Results:

(foo :a 1 :b 2 :c 3)  ==> (1 2 3 T)
(foo :c 3 :b 2 :a 1)  ==> (1 2 3 T)
(foo :a 1 :c 3)       ==> (1 20 3 T)
(foo)                 ==> (NIL 20 30 NIL)

So if I use &key at the beginning of my parameter list, I have the possibility to use a list of 3 parameters name, default value and the third if the parameter as been supplied or not. Ok. But looking at the code in the above example:

(list a b c c-p)

How does the lisp interpreter know that c-p is my "supplied parameter"?

+4  A: 

It's difficult to tell what you are asking. c-p is bound to T or NIL, depending on whether c is supplied as a parameter. This binding is then available to the body of the function.

Marcelo Cantos
Aaah got it :-) c-p is simply added to the list like a, b and c and is not a "supplied parameter" for "a list was set/unset". It takes some time to become accustomed with the syntax, although its really easy. :-) Thanks!
echox
+11  A: 

Let's reindent the function foo:

(defun foo (&key a
                 (b 20)
                 (c 30 c-p))
   (list a b c c-p))

If you indent it like this you will see that the function has three keyword parameters: a, b and c. These are available in the body of the function.

For the keyword parameter c there is a variable declared c-p that will be T or NIL depending whether c has been passed when foo gets called.

A keyword parameter generally can be declared as one of the following options:

  1. as a single variable name
  2. a list of a variable name and a default value
  3. a list of a variable name, a default value and a variable that will show whether the parameter has been passed or not when the function gets called

The supplied-p is particularly interesting when one wants to see whether the value comes from the call or the default value:

(defun make-my-array (size &key (init-value nil init-value-supplied-p))
   (if init-value-supplied-p
       (make-array size :initial-element init-value)
       (make-array size)))

Now the user can init the elements to NIL:

(make-my-array 10 :init-value nil)

Here the default value and the supplied value can both be NIL, but we need to make a difference. The variable init-value-supplied-p makes it possible to see whether the NIL value of the variable init-value comes from the default or from the function call.

Rainer Joswig