leo@maui.cs.ucla.edu (08/10/88)
There seems to be at least one case where &optional arguments are actually required. Here is a simple function I was trying to define: (defun test-args (req1 &optional (opt1 'opt1) &key (key1 'key1) (key2 'key2)) (format t "Arguments:~%~%") (format t "REQ1: ~A~%" req1) (format t "OPT1: ~A~%" opt1) (format t "KEY1: ~A~%" key1) (format t "KEY2: ~A~%" key2) (format t "~%") (values)) Seems fine so far. Now, when you call TEST-ARGS with arguments 1 2 :key1 3 everything is fine. However, arguments 1 :key1 2 result in an error. The optional argument must be supplied before the keyowrd arguments. In CLtL, the examples of the mixtures of different types of arguments never showed a case where &optional was NOT supplied and &key was used. It also follows the description of the argument processing in CLtL. However, doesn't this defeat the purpose for &optional arguments?
rcp@perseus.SW.MCC.COM (Rob Pettengill) (08/11/88)
In article <15115@shemp.CS.UCLA.EDU> leo@CS.UCLA.EDU (Leonid V. Belyaev) writes:
;There seems to be at least one case where &optional arguments are actually
;required. Here is a simple function I was trying to define:
;
; (defun test-args (req1 &optional (opt1 'opt1)
; &key (key1 'key1)
; (key2 'key2))
; (format t "Arguments:~%~%")
; (format t "REQ1: ~A~%" req1)
; (format t "OPT1: ~A~%" opt1)
; (format t "KEY1: ~A~%" key1)
; (format t "KEY2: ~A~%" key2)
; (format t "~%")
; (values))
;
;Seems fine so far. Now, when you call TEST-ARGS with arguments
;
; 1 2 :key1 3
;
;everything is fine. However, arguments
;
; 1 :key1 2
;
;result in an error. The optional argument must be supplied before the
; ...
When an optional argument beyond the first one is to be supplied then
all of the preceeding optional arguments must be supplied. In order
to avoid ambiguity in the interpretation of the values passed, all
optional arguments must be specified before keyword arguments when
both are passed. Zetalisp used to distinquish between required and
optional keyword arguments - Common Lisp has only optional keyword
arguments. Read the description of lambda list processing in Section
5.2.2 (page 61). All optional parameters are bound before any keyword
parameters are bound. This is exactly the behavior you describe.
;rob
barmar@think.COM (Barry Margolin) (08/12/88)
In article <15115@shemp.CS.UCLA.EDU> leo@CS.UCLA.EDU (Leonid V. Belyaev) writes: > (defun test-args (req1 &optional (opt1 'opt1) > &key (key1 'key1) > (key2 'key2)) > >Seems fine so far. Now, when you call TEST-ARGS with arguments > > 1 2 :key1 3 > >everything is fine. However, arguments > > 1 :key1 2 > >result in an error. This is true. All "positional" arguments must be specified before any keyword arguments. The reason is that a keyword is a perfectly valid value for an optional argument. So, in your second call, REQ1 is given the value 1, OPT1 is given the value :KEY1, and then it tries to parse the rest of the arguments as keyword arguments, which results in the error you got. There's no way to get rid of this restriction except by making keywords invalid as values for optional arguments, which is a very unlikely thing to happen. >However, doesn't this defeat the purpose for &optional arguments? Not really. Consider a function that has two optional arguments. You can't supply the second optional argument without supplying the first. This doesn't defeat the purpose of making the first one optional, although it is somewhat less convenient. The programmer has decided that a caller that needs to specify the second optional argument is likely to want to specify the first, too. Think of the keywords as a set of "last" optional arguments, which may be in any order among themselves. In general, I think it is poor style to have both &optional and &key arguments. Any function that has more than about three optional arguments should probably make them all &key. The whole point of &key arguments is to solve the problem where the caller only wants to specify some of the optional arguments. Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar