From: Mark Carroll
Subject: Keyword arguments
Date: 
Message-ID: <Gsk*6F49n@news.chiark.greenend.org.uk>
I have a function,

USER(11): (describe #'gfp:get-frame-name)
#<Function GET-FRAME-NAME> is a COMPILED-FUNCTION.
  The arguments are (GFP::FRAME &KEY GFP:KB GFP::ERROR-P)
USER(12): 

Let's assume that we never use the keyword arguments, and always pass
something for GFP::FRAME that has no side effects when evaluated.

A simple wrapper like,

(defmacro get-frame-name (frame &key kb)
  `(if ,kb (gfp::get-frame-name ,frame :kb ,kb)
     (gfp::get-frame-name ,frame)))

(from the USER package) works fine. However, it stops working if I
change the first ,kb (after 'if') to t, giving "No methods applicable
for generic function" for some internal function that get-frame-name
calls.

What I want to know is, seeing that the call to describe reveals no
odd default values for GFP:KB, why has the behaviour changed? Doesn't
GFP:KB get a value of nil in either case? I'm sure I'm not
understanding something fundamental, to be surprised by this.

-- Mark

From: Erik Naggum
Subject: Re: Keyword arguments
Date: 
Message-ID: <3146303318559517@naggum.no>
* Mark Carroll
| A simple wrapper like,
| 
| (defmacro get-frame-name (frame &key kb)
|   `(if ,kb (gfp::get-frame-name ,frame :kb ,kb)
|      (gfp::get-frame-name ,frame)))

  hmmm.

| (from the USER package) works fine.  However, it stops working if I
| change the first ,kb (after 'if') to t, giving "No methods applicable for
| generic function" for some internal function that get-frame-name calls.

  a more precise reproduction of the error message would probably be a lot
  more revealing of the actual problem.

| What I want to know is, seeing that the call to describe reveals no odd
| default values for GFP:KB, why has the behaviour changed?  Doesn't GFP:KB
| get a value of nil in either case?  I'm sure I'm not understanding
| something fundamental, to be surprised by this.

  I'm not sure you should rely on such information as heavily as you do.
  here's an example that shows you the effect:

CL-USER(85): (defun foo (&key (zot t)))
FOO
CL-USER(86): (arglist #'foo)
(&KEY (ZOT T))
T
CL-USER(87): (compile **)
; While compiling FOO:
Warning: Variable ZOT is never used.
FOO
T
NIL
CL-USER(88): (arglist #'foo)
(&KEY ZOT)
T

  first of all, I don't understand theneed for your wrapper.  if it does
  what you show us in that example, you could just import the symbol and
  get rid of the problem.  but supposing there's any use for this wrapper
  in the first place, I'd do something very similar to this:

(defmacro get-frame-name (&rest args)
  `(gfp::get-frame-name ,@args))

#:Erik
From: Kent M Pitman
Subject: Re: Keyword arguments
Date: 
Message-ID: <sfwr9k1wqh4.fsf@world.std.com>
Mark Carroll <·····@chiark.greenend.org.uk> writes:

> I have a function,
> 
> USER(11): (describe #'gfp:get-frame-name)
> #<Function GET-FRAME-NAME> is a COMPILED-FUNCTION.
>   The arguments are (GFP::FRAME &KEY GFP:KB GFP::ERROR-P)
> USER(12): 
> 
> Let's assume that we never use the keyword arguments, and always pass
> something for GFP::FRAME that has no side effects when evaluated.
> 
> A simple wrapper like,
> 
> (defmacro get-frame-name (frame &key kb)
>   `(if ,kb (gfp::get-frame-name ,frame :kb ,kb)
>      (gfp::get-frame-name ,frame)))
> 
> (from the USER package) works fine. However, it stops working if I
> change the first ,kb (after 'if') to t, giving "No methods applicable
> for generic function" for some internal function that get-frame-name
> calls.
> 
> What I want to know is, seeing that the call to describe reveals no
> odd default values for GFP:KB, why has the behaviour changed? Doesn't
> GFP:KB get a value of nil in either case? 

Yes.

> I'm sure I'm not
> understanding something fundamental, to be surprised by this.

IF I HAD MY GUESS, I'd say you're not understanding that your
implementation is capable of having a bug.  When you talk to people
about baffling behaviors, please specify not only the vendor (which
you didn't even do here) but the implementation version (since bugs
get fixed).

The code you offer above works as you'd expect in Harlequin LispWorks
for Windows 4.1 and in Franz ACL 5.0.  It gets no-such-method in the
cases where the first argument doesn't match (since the first arg is
all that's being dispatched on) and it has identical behavior between
the two arms in the other cases (well, my function was written to just
print out the values).

(in-package "GFP")
(defmethod get-frame-name ((frame frame) &key kb error-p)
  (format t "~&In GET-FRAME-NAME, FRAME=~S KB=~S ERROR-P=~S~%"
	  frame kb error-p))
(in-package "CL-USER")
(defmacro gfn1 (frame &key kb)
  `(if ,kb (gfp::get-frame-name ,frame :kb ,kb)
     (gfp::get-frame-name ,frame)))
(defmacro gfn2 (frame &key kb)
  `(if t (gfp::get-frame-name ,frame :kb ,kb)
     (gfp::get-frame-name ,frame)))
(defvar *frame*)
(defun test-it ()
  (let ((*frame* (make-instance 'gfp::frame :name (gensym))))
    (dolist (form '((gfn1 *frame* :kb t)
                    (gfn1 *frame* :kb nil)
                    (gfn1 *frame*)
                    (gfn2 'some-symbol :kb t)
                    (gfn2 'some-symbol :kb nil)
                    (gfn2 'some-symbol))))
      (format t "~&Form: ~S" form)
      (handler-case (format t "~& ==>  ~S~%" (eval form))
        (error (c) (format t "~&An error resulted:~%~A" c))))))
(test-it)

Both Allegro and Harlequin give something essentially like this.
All of the following seem ok to me...

 Form: (GFN1 *FRAME* :KB T)
 In GET-FRAME-NAME, FRAME=#<GFP::FRAME 2041C29C> KB=T ERROR-P=NIL
  ==>  NIL
 Form: (GFN1 *FRAME* :KB NIL)
 In GET-FRAME-NAME, FRAME=#<GFP::FRAME 2041C29C> KB=NIL ERROR-P=NIL
  ==>  NIL
 Form: (GFN1 *FRAME*)
 In GET-FRAME-NAME, FRAME=#<GFP::FRAME 2041C29C> KB=NIL ERROR-P=NIL
  ==>  NIL
 Form: (GFN2 (QUOTE SOME-SYMBOL) :KB T)
 An error resulted:
 No applicable methods for
    #<GF GFP::GET-FRAME-NAME> with args (SOME-SYMBOL :KB T)
 Form: (GFN2 (QUOTE SOME-SYMBOL) :KB NIL)
 An error resulted:
 No applicable methods for 
    #<GF GFP::GET-FRAME-NAME> with args (SOME-SYMBOL :KB NIL)
 Form: (GFN2 (QUOTE SOME-SYMBOL))
 An error resulted:
 No applicable methods for
    #<GF GFP::GET-FRAME-NAME> with args (SOME-SYMBOL :KB NIL)
From: Tim Bradshaw
Subject: Re: Keyword arguments
Date: 
Message-ID: <ey3emg1vk8i.fsf@lostwithiel.tfeb.org>
* Mark Carroll wrote:

> What I want to know is, seeing that the call to describe reveals no
> odd default values for GFP:KB, why has the behaviour changed? Doesn't
> GFP:KB get a value of nil in either case? I'm sure I'm not
> understanding something fundamental, to be surprised by this.

As far as I know DESCRIBE in Allegro (which I'm assuming you are using
from the prompt) does not tell you if there are default values for
keyword arguments.  So you end up calling it with NIL as the keyword
argument, which is different, I guess, than not supplying it.

--tim
From: Mark Carroll
Subject: Re: Keyword arguments
Date: 
Message-ID: <tBE*UR59n@news.chiark.greenend.org.uk>
In article <···············@lostwithiel.tfeb.org>,
Tim Bradshaw  <···@tfeb.org> wrote:
>* Mark Carroll wrote:
>
>> What I want to know is, seeing that the call to describe reveals no
>> odd default values for GFP:KB, why has the behaviour changed? Doesn't
>> GFP:KB get a value of nil in either case? I'm sure I'm not
>> understanding something fundamental, to be surprised by this.
>
>As far as I know DESCRIBE in Allegro (which I'm assuming you are using
>from the prompt) does not tell you if there are default values for

Sorry - yes, I should have said - the article got rewritten a lot...

>keyword arguments.  So you end up calling it with NIL as the keyword
>argument, which is different, I guess, than not supplying it.

Ah - thanks, yes, I'd checked that DESCRIBE gives me the keyword
arguments' defaults for regular functions, but Erik's article makes me
think that maybe it doesn't after compilation. (-:

-- Mark