From: Larry Clapp
Subject: Macro style question: conditional code
Date: 
Message-ID: <q9vr1b.v1d.ln@theclapp.ddts.net>
Hi, all,

Given

    (defclass a ())
    (defclass b (a))
    (defclass c (b))

I have a macro that looks something like this

    (defmacro def-a-method (class name)
      `(defmethod ,name ((arg ,class))
	 ; ... other code ...
	 ,@(unless (eq class 'a)
	     `((if (next-method-p)
		 (call-next-method))))))

So if I call (def-a-method a name1) it defines a method that doesn't
call its next method (which wouldn't exist), whereas if I call
(def-a-method b name1) or (def-a-method c name1) it defines a method
that does.

Primarily, I'd like to know if I've missed some better way to include
code conditionally than

    `(...
       ,@(unless <test>
	   `((blah)
	     (blah)
	     (blah))))

Secondarily, would you really consider the def-a-method macro good
style given what I want it to do?

(I understand I can only use def-a-method with A or one of its
subclasses.)

Thanks for your input.

-- 
Larry Clapp / ·····@theclapp.org
Use Lisp from Vim: VILisp: http://vim.sourceforge.net/script.php?script_id=221


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

From: Barry Margolin
Subject: Re: Macro style question: conditional code
Date: 
Message-ID: <Fyf0a.23$hw1.1467@paloalto-snr1.gtei.net>
In article <·············@theclapp.ddts.net>,
Larry Clapp  <·····@theclapp.org> wrote:
>Hi, all,
>
>Given
>
>    (defclass a ())
>    (defclass b (a))
>    (defclass c (b))
>
>I have a macro that looks something like this
>
>    (defmacro def-a-method (class name)
>      `(defmethod ,name ((arg ,class))
>	 ; ... other code ...
>	 ,@(unless (eq class 'a)
>	     `((if (next-method-p)
>		 (call-next-method))))))
>
>So if I call (def-a-method a name1) it defines a method that doesn't
>call its next method (which wouldn't exist), whereas if I call
>(def-a-method b name1) or (def-a-method c name1) it defines a method
>that does.
>
>Primarily, I'd like to know if I've missed some better way to include
>code conditionally than
>
>    `(...
>       ,@(unless <test>
>	   `((blah)
>	     (blah)
>	     (blah))))

That seems like the right idiom to me.

>Secondarily, would you really consider the def-a-method macro good
>style given what I want it to do?

I'm not crazy about the fact that a specific class name is hard-coded into
the macro, as it's not very general.  Other ways to do this would be:

* A parameter that specifies whether the (call-next-method) code should be
  generated.
* Keep a separate list of classes that should be treated specially like
  this.

I'm not sure why you need to do this conditional inclusion in the first
place, though.  You're calling NEXT-METHOD-P first, so you won't actually
try to call CALL-NEXT-METHOD in class A.

-- 
Barry Margolin, ······@genuity.com
Genuity Managed Services, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Larry Clapp
Subject: Re: Macro style question: conditional code
Date: 
Message-ID: <kf2s1b.u8e.ln@theclapp.ddts.net>
In article <·················@paloalto-snr1.gtei.net>, Barry Margolin
wrote:
> In article <·············@theclapp.ddts.net>, Larry Clapp
> <·····@theclapp.org> wrote:
>> Given
>> 
>>     (defclass a ())
>>     (defclass b (a))
>>     (defclass c (b))
>> 
>> I have a macro that looks something like this
>> 
>>     (defmacro def-a-method (class name)
>>       `(defmethod ,name ((arg ,class))
>> 	 ; ... other code ...
>> 	 ,@(unless (eq class 'a)
>> 	     `((if (next-method-p)
>> 		 (call-next-method))))))
>> 
>> So if I call (def-a-method a name1) it defines a method that
>> doesn't call its next method (which wouldn't exist), whereas if I
>> call (def-a-method b name1) or (def-a-method c name1) it defines a
>> method that does.
>> 
>> Primarily, I'd like to know if I've missed some better way to
>> include code conditionally than
>> 
>>     `(...
>>        ,@(unless <test>
>> 	   `((blah)
>> 	     (blah)
>> 	     (blah))))
>  
> That seems like the right idiom to me.

Okay, thanks.  It just looked weird, and using '(...) when I should've
used (list ...) has bitten me before, so I thought I'd ask, since it
seemed kind of similar.

[Alternative methods snipped]
> I'm not sure why you need to do this conditional inclusion in the
> first place, though.  You're calling NEXT-METHOD-P first, so you
> won't actually try to call CALL-NEXT-METHOD in class A.

I figured if I can determine at compile time that I won't have a next
method, I shouldn't even try it.  On the other hand, perhaps this
falls under the category of "early optimization".

Thanks for your feedback!

-- 
Larry Clapp / ·····@theclapp.org
Use Lisp from Vim: VILisp: http://vim.sourceforge.net/script.php?script_id=221


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----
From: Frank A. Adrian
Subject: Re: Macro style question: conditional code
Date: 
Message-ID: <k9m0a.2250$eL4.169156@news.uswest.net>
Larry Clapp wrote:

> I figured if I can determine at compile time that I won't have a next
> method, I shouldn't even try it.  On the other hand, perhaps this
> falls under the category of "early optimization".

Actually, it falls under the category of "potentially error prone".  If 
class a is ever redefined to have a superclass that has a method of the 
same name, the defmethod as macroexpanded (and potentially what the generic 
function was based upon) could still assume that there is no next method.  
This might lead to some difficult to detect faults.  Remember that Lisp is 
a dynamic language and that tests like next-method-p are available at run 
time for a purpose.  You might think that you'll never add a superclass to 
a.  Actually, this compounds the probability of error because you'll be 
sure to forget your little optimization until something breaks.  Code 
cleanly.  The cute trick you're playing to optimize the call may not even 
be necessary.  It is quite possible that it will eventually become 
erroneous.

faa
From: Kenny Tilton
Subject: Re: Macro style question: conditional code
Date: 
Message-ID: <3E4A7CC8.9050907@nyc.rr.com>
Larry Clapp wrote:
> Hi, all,
> 
> Given
> 
>     (defclass a ())
>     (defclass b (a))
>     (defclass c (b))
> 
> I have a macro that looks something like this
> 
>     (defmacro def-a-method (class name)
>       `(defmethod ,name ((arg ,class))
> 	 ; ... other code ...
> 	 ,@(unless (eq class 'a)
> 	     `((if (next-method-p)
> 		 (call-next-method))))))
> 
> So if I call (def-a-method a name1) it defines a method that doesn't
> call its next method (which wouldn't exist), whereas if I call
> (def-a-method b name1) or (def-a-method c name1) it defines a method
> that does.
> 
> Primarily, I'd like to know if I've missed some better way to include
> code conditionally than
> 
>     `(...
>        ,@(unless <test>
> 	   `((blah)
> 	     (blah)
> 	     (blah))))
> 
> Secondarily, would you really consider the def-a-method macro good
> style given what I want it to do?

Purely regarding macro style, I would switch the order of the class and 
name args to resonate with the way those appear when defining a method. 
And You kinda left out how other code gets into the game:

(defmacro def-a-method ((method-name class-name) &body other-code)
    ...etc)

So uses look like:

(def-a-method (do-print IXBitMap)
    (ix-print-bitmap (the-bmp arg) printer-stream))

Uh-oh. No way to pass in arguments such as the printer-stream. And I 
don't like arg as name for what in Smalltalk is called 'self'. So:

(defmacro def-a-method ((method-name class-name) (&rest args)
                          (&body other-code)
    ...etc)

I don't know. The bigger problem here is using a macro to do something 
CLOS can do out of the box.

For one, why cannot a method on A include code like this?:

 > 	     `((if (next-method-p)
 > 		 (call-next-method))))))

Since you are checking for next-method-p you'll be OK.

But more importantly, why not use method-combination PROGN? That is what 
def-a-method is doing, reinventing PROGN over whatever methods happen to 
apply.

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
  the bath water is cold." -- Lorraine Lee Cudmore
From: Larry Clapp
Subject: Re: Macro style question: conditional code
Date: 
Message-ID: <6q5e2b.qio.ln@theclapp.ddts.net>
In article <················@nyc.rr.com>, Kenny Tilton wrote:
> Larry Clapp wrote:
>> Hi, all,
>> 
>> Given
>> 
>>     (defclass a ())
>>     (defclass b (a))
>>     (defclass c (b))
>> 
>> I have a macro that looks something like this
>> 
>>     (defmacro def-a-method (class name)
>>       `(defmethod ,name ((arg ,class))
>> 	 ; ... other code ...
>> 	 ,@(unless (eq class 'a)
>> 	     `((if (next-method-p)
>> 		 (call-next-method))))))
>> 
>> So if I call (def-a-method a name1) it defines a method that
>> doesn't call its next method (which wouldn't exist), whereas if I
>> call (def-a-method b name1) or (def-a-method c name1) it defines a
>> method that does.
>> 
>> Primarily, I'd like to know if I've missed some better way to
>> include code conditionally than
>> 
>>     `(...
>>        ,@(unless <test>
>> 	   `((blah)
>> 	     (blah)
>> 	     (blah))))
>> 
>> Secondarily, would you really consider the def-a-method macro good
>> style given what I want it to do?
> 
> Purely regarding macro style, I would switch the order of the class
> and name args to resonate with the way those appear when defining a
> method.  And You kinda left out how other code gets into the game:
> 
> (defmacro def-a-method ((method-name class-name) &body other-code)
>     ...etc)
> 
> So uses look like:
> 
> (def-a-method (do-print IXBitMap)
>     (ix-print-bitmap (the-bmp arg) printer-stream))
> 
> Uh-oh. No way to pass in arguments such as the printer-stream. And I 
> don't like arg as name for what in Smalltalk is called 'self'. So:
> 
> (defmacro def-a-method ((method-name class-name) (&rest args)
>                           (&body other-code)
>     ...etc)

Good point, but not applicable to my (admittedly homework-ish) usage.
The full code looks more like this:

    (defmacro def-cleanser-method (type name msg)
      `(defmethod ,name ((this ,type))
	 (my-append this ,(concatenate 'string " " msg "()"))
	 (if (next-method-p)
	   (call-next-method))))

(I already took out the

    (unless (eq class 'a)
      ... )

stuff based on some earlier advice in this group, i.e. "why worry
about it given that I use next-method-p anyway", which you mentioned
too, and "what happens if I ever redefine class A as a subclass of
something else?")

So, I had no "&body body" clause because I really did have no body.
Apologies for posting a too-stripped-down example.

> The bigger problem here is using a macro to do something CLOS can do
> out of the box.
[snip]
> [W]hy not use method-combination PROGN? That is what def-a-method is
> doing, reinventing PROGN over whatever methods happen to apply.

Because I didn't remember it.  Mea culpa.  The CLHS entry for
DEFMETHOD doesn't mention it, and I'd forgotten about Graham
mentioning it (in passing).  Thanks for pointing that out!

-- 
Larry Clapp / ·····@theclapp.org
Use Lisp from Vim: VILisp: http://vim.sourceforge.net/script.php?script_id=221


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----