From: bufie
Subject: using defmacro to "wrap" a function
Date: 
Message-ID: <szNXc.71389$Fg5.22343@attbi_s53>
Hi,

I've been able to use defmacro to define a few simple macros, but I'm having
trouble with this one.

On occasion I want to prevent a function from being traced, so in the past I
have hand-coded a macro (thanks to some help from this list!) something like
this (for example, if I wanted to prevent boundp from being traced):

(defmacro my-boundp (name)
  `(let ((*trace-output* (make-broadcast-stream)))
     (boundp ,name)
     )
  )

This is pretty simple, obviously.  What I'd like to do is have a macro that
can automatically define the above macro, something like this:

(defmacro my-notrace (funcname)
  (let ((newname (format nil "ai-~A" fname)))
    `(defmacro ',newname (&rest args)
       (display args)
       )
    )
  )

so that if I then call
(my-notrace boundp)

the above my-boundp macro definition will be created...

Any thoughts?

Thanks!

bufie

From: Joost Kremers
Subject: Re: using defmacro to "wrap" a function
Date: 
Message-ID: <slrnciva8a.d9.joostkremers@j.kremers4.news.arnhem.chello.nl>
bufie wrote:
> On occasion I want to prevent a function from being traced, so in the past I
> have hand-coded a macro (thanks to some help from this list!) something like
> this (for example, if I wanted to prevent boundp from being traced):
>
> (defmacro my-boundp (name)
>   `(let ((*trace-output* (make-broadcast-stream)))
>      (boundp ,name)
>      )
>   )
>
> This is pretty simple, obviously.  What I'd like to do is have a macro that
> can automatically define the above macro, something like this:
>
> (defmacro my-notrace (funcname)
>   (let ((newname (format nil "ai-~A" fname)))
>     `(defmacro ',newname (&rest args)
>        (display args)
>        )
>     )
>   )
>
> so that if I then call
> (my-notrace boundp)
>
> the above my-boundp macro definition will be created...

ok, but how are you then going to use that macro in your code?

shouldn't you be creating a macro WITH-NO-TRACE? something like:

(defmacro with-no-trace (&rest body)
  `(let ((*trace-output* (make-broadcast-stream)))
      ,@body))

so that you can simply do:

  ....
  (with-no-trace (boundp name))
  ....

or am i saying something stupid here? (might as well be. lisp is usually a
lot cleverer than i think. ;-)

-- 
Joost Kremers                                      ············@yahoo.com
Selbst in die Unterwelt dringt durch Spalten Licht
EN:SiS(9)
From: bufie
Subject: Re: using defmacro to "wrap" a function
Date: 
Message-ID: <CuSXc.246434$eM2.110652@attbi_s51>
Thanks, Joost!  This is just what I was looking for!  (and *so* much nicer
than what I was thinking!)

Thanks again!

bufie

"Joost Kremers" <············@yahoo.com> wrote in message
·······························@j.kremers4.news.arnhem.chello.nl...
> bufie wrote:
> > On occasion I want to prevent a function from being traced, so in the
past I
> > have hand-coded a macro (thanks to some help from this list!) something
like
> > this (for example, if I wanted to prevent boundp from being traced):
> >
> > (defmacro my-boundp (name)
> >   `(let ((*trace-output* (make-broadcast-stream)))
> >      (boundp ,name)
> >      )
> >   )
> >
> > This is pretty simple, obviously.  What I'd like to do is have a macro
that
> > can automatically define the above macro, something like this:
> >
> > (defmacro my-notrace (funcname)
> >   (let ((newname (format nil "ai-~A" fname)))
> >     `(defmacro ',newname (&rest args)
> >        (display args)
> >        )
> >     )
> >   )
> >
> > so that if I then call
> > (my-notrace boundp)
> >
> > the above my-boundp macro definition will be created...
>
> ok, but how are you then going to use that macro in your code?
>
> shouldn't you be creating a macro WITH-NO-TRACE? something like:
>
> (defmacro with-no-trace (&rest body)
>   `(let ((*trace-output* (make-broadcast-stream)))
>       ,@body))
>
> so that you can simply do:
>
>   ....
>   (with-no-trace (boundp name))
>   ....
>
> or am i saying something stupid here? (might as well be. lisp is usually a
> lot cleverer than i think. ;-)
>
> -- 
> Joost Kremers                                      ············@yahoo.com
> Selbst in die Unterwelt dringt durch Spalten Licht
> EN:SiS(9)
From: Pascal Costanza
Subject: Re: using defmacro to "wrap" a function
Date: 
Message-ID: <cgoanp$8fv$1@newsreader3.netcologne.de>
bufie wrote:

> Hi,
> 
> I've been able to use defmacro to define a few simple macros, but I'm having
> trouble with this one.
> 
> On occasion I want to prevent a function from being traced, so in the past I
> have hand-coded a macro (thanks to some help from this list!) something like
> this (for example, if I wanted to prevent boundp from being traced):
> 
> (defmacro my-boundp (name)
>   `(let ((*trace-output* (make-broadcast-stream)))
>      (boundp ,name)
>      )
>   )

First of all, change your use of parentheses. Placing each closing 
parenthesis on a separate line doesn't buy you anything, but just wastes 
valuable screen space. The better you utilize vertical screen space, the 
easier it is to understand larger sections of your code.

Second, the functionality you describe doesn't need a macro. It's 
sufficient to wrap this in a function:

(defun my-boundp (name)
   (let ((*trace-output* (make-broadcast-stream)))
     (boundp name)))

The general rule of thumb is this: Macros are very powerful, but only 
use them when functions won't do the job. In case you need the 
efficiency of your code being inlined, you can just do this:

(declaim (inline my-boundp))

...but note that even this may be a premature optimization that can turn 
out to actually decrease the overall performance of your program. Never 
optimize anything without a proper profile of actual runs of your program.

> This is pretty simple, obviously.  What I'd like to do is have a macro that
> can automatically define the above macro, something like this:
> 
> (defmacro my-notrace (funcname)
>   (let ((newname (format nil "ai-~A" fname)))
>     `(defmacro ',newname (&rest args)
>        (display args)
>        )
>     )
>   )
> 
> so that if I then call
> (my-notrace boundp)
> 
> the above my-boundp macro definition will be created...

(defmacro my-notrace (fname newname &optional (inline nil))
   `(progn
      (defun ,newname (&rest args)
        (let ((*trace-output* (make-broadcast-stream)))
          (apply #',fname args)))
      ,@(when inline
          (list `(declaim (inline ,newname))
                `',newname))))

A few minor notes:

- `(defun ',newname ...) is wrong - the DEFUN macro doesn't evaluate its 
second argument, so you must not quote it.

- Don't automatically generate names based on some name pattern. There 
are only few macros that do this, and this usually creates problems, 
because the new names may clash with existing other names. Furthermore, 
it makes your code harder to understand because you suddenly start to 
use names that you haven't explicitly defined before. Therefore it's 
better to have the newly generated name passed as an explicit parameter 
to your macro, so that you have better traces of what you have actually 
done.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Vassil Nikolov
Subject: Re: using defmacro to "wrap" a function
Date: 
Message-ID: <lzacwfjmyd.fsf@janus.vassil.nikolov.names>
"bufie" <·····@spamneggs.com> writes:

> [...]
> What I'd like to do is have a macro that
> can automatically define the above macro, something like this:
>
> (defmacro my-notrace (funcname)
>   (let ((newname (format nil "ai-~A" fname)))
>     `(defmacro ',newname (&rest args)
>        (display args)
>        )
>     )
>   )
>
> so that if I then call
> (my-notrace boundp)
>
> the above my-boundp macro definition will be created...


  About naming, independently of the other comments in this thread:

  When defining a macro that expands into a DEF-form (e.g. DEFCLASS,
  DEFMACRO, DEFUN, DEFVAR), it is a good idea to have the name of the
  macro start with DEFINE- or DEF, too---in this case, something like
  DEFINE-UNTRACEABLE-FUNCTION.  To me, a macro called NOTRACE would
  appear to suppress tracing, rather than define something that is not
  susceptible to tracing.

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.