bds@mbunix.mitre.org (Barry D Smith) (08/23/89)
Since we were just burnt by this on a Symbolics, I wonder if anyone would comment: Given the function: (defun test (a b &optional (c 0) &key (d 1)) (if (= d 1) (+ a b c d) (+ a b c))) (test 5 4 :d 0) results in an error. Since optional arguments are evaluated first, c is bound to :d, and 0 isn't a key argument. Is this the Common Lisp standard? If so, does it make sense? In our case, we had 3 optional arguments, and we wanted to use the default values, but to set the key argument to something else. It seems a violation of the notion of optional arguments to have to specify them. Barry Smith
shiffman%basselope@Sun.COM (Hank Shiffman) (08/27/89)
In article <64922@linus.UUCP> bds@mbunix (Smith) writes: >Since we were just burnt by this on a Symbolics, I wonder >if anyone would comment: > >Given the function: > >(defun test (a b &optional (c 0) &key (d 1))... > >(test 5 4 :d 0) results in an error. > Yep. This is just the way things are supposed to work. If you have both optional and keyword arguments, you must provide *all* the optional arguments to get access to any of the optional ones. -- Hank Shiffman (415) 336-4658 Marketing Technical Specialist Software Engineering Technologies ...!sun!shiffman Sun Microsystems, Inc. shiffman@Sun.com
barmar@think.COM (Barry Margolin) (08/28/89)
In article <64922@linus.UUCP> bds@mbunix (Smith) writes: >(defun test (a b &optional (c 0) &key (d 1)) >(test 5 4 :d 0) results in an error. >Is this the Common Lisp standard? Yes. See p.61 of CLtL. Optional arguments are processed before keyword arguments. > If so, does it make sense? Yes. How would you propose that Lisp determine whether the :D is supposed to be an argument name or the value of the C argument? In the above case *you* can tell that it was intended as an argument name because you gave an incorrect number of arguments, but that isn't always possible. Consider: (defun test (&optional a b &key d) ...) (test :d :e) This binds A to :D, B to :E, and D to NIL and gets no error. How would a Lisp system determine that you actually meant to set the D argument? Don't try to special case arguments that are symbols in the KEYWORD package. First of all, that would break lots of things; many functions that keyword-valued arguments. Second, argument names don't even have to be in the KEYWORD package; consider: (defun test (&optional a b &key ((c-name c) nil)) ...) (test 'c-name 'c-val) This binds A to C-NAME, B to C-VAL, and C to NIL. Lisp can't tell that you meant it to be interpreted as (test nil nil 'c-name 'c-val) >In our case, we had 3 optional arguments, and we >wanted to use the default values, but to set the key argument to >something else. This is why it's generally a bad idea to have both optional and keyword arguments in the same function. You should turn them all into keyword arguments. >It seems a violation of the notion of optional >arguments to have to specify them. Well, you have to specify the Nth optional argument if you want to specify the N+1th one. Named arguments can be thought of as a single, last optional argument which is automatically parsed. Or they can be considered as automatically-parsed &REST arguments. Either of these analogies will help you remember that optional arguments must be specified first. Lisp isn't Ada. Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
jeff@aiai.uucp (Jeff Dalton) (08/28/89)
In article <64922@linus.UUCP> bds@mbunix (Smith) writes: >(defun test (a b &optional (c 0) &key (d 1)) > (if (= d 1) > (+ a b c d) > (+ a b c))) >(test 5 4 :d 0) results in an error. >Since optional arguments are evaluated first, c is bound to :d, and 0 >isn't a key argument. Is this the Common Lisp standard? If so, does >it make sense? In our case, we had 3 optional arguments, and we >wanted to use the default values, but to set the key argument to >something else. It seems a violation of the notion of optional >arguments to have to specify them. This behavior is correct Common Lisp. To specify any arguments that occur after the optional ones, you have to specify the optional arguments. The reason it may look strange in this case is that you seem to be supposing that use of a keyword in a function call should automatically indicate a keyword parameter. However, keywords are just a kind of symbol and are used for a number of different purposes. For example, in (LIST :A :B) => (:A :B), both :A and :B are used just as data objects, and neither indicates that a keyword parameter should follow. If you never want to use keywords except to indicate keyword parameters, you may well think that Common Lisp has made a mistake. But many programmers do use keywords for other purposes. For example, in some object systems, keywords are used a method names, as in (send aWindow :redisplay) -- Jeff
miller@CS.ROCHESTER.EDU (Brad Miller) (08/29/89)
Since optional arguments are evaluated first, c is bound to :d, and 0 isn't a key argument. Is this the Common Lisp standard? Yes; for a detailed description, read page 61 of CLtL, and the copious examples on pgs. 63-65. If so, does it make sense? How else could you do it? (for generality, remember to handle the case of two optional args, the first of which expects an argument of type keyword) If you *really* want the effect of both, try not specifying either optional or keyword args, but &rest only, and then process it yourself according to any arcane rules you like... or write your own version of Defun (Defunny?) that handles the lambda list for you by your own rules... and having a sample implementation is 50% of getting something into the standard. Are we having fun yet? :-)