Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Overwriting Functions/Macros?

23 views
Skip to first unread message

wan...@exploited.barmy.army

unread,
Mar 31, 1998, 3:00:00 AM3/31/98
to

Hi all,

I would like to reimplement a built in macro and have my new
implementation call the old one. For example, given macro x
I would like to do something like:

(defmacro x
`(... call-old-x ...))

I tried storing the original macro in a variable (setq v #'macro-name),
but then I could not find out how to call it (a macro equivalent to
funcall?). Also, I'm not sure if (setq v #'macro-name) is guaranteed
to work on all implementations.

So what would be the best way of accomplishing this, if it is possible?

I looked through Cltl2, but could find nothing.

Also, while I did manage to get this to work with functions I am
also suspicious of my implementation. I did:

(setq f #'function-name)

(defun function-name (...)
(...
(funcall f ...)))

The problem is I don't know if this is standard behavior. Is this
a good idea, or is there a better way?

IN particular, what has me worried is the prospect of having
f point to an address with function-name in memory that is overwritten by
the new definition.

Thanks in advance for any assistance offered.


--
Ahmed

To respond via email, send email to punkrock at cs dot uh dot edu

Erik Naggum

unread,
Mar 31, 1998, 3:00:00 AM3/31/98
to

* wan...@exploited.barmy.army

| Hi all,
|
| I would like to reimplement a built in macro and have my new
| implementation call the old one. For example, given macro x
| I would like to do something like:
|
| (defmacro x
| `(... call-old-x ...))

(defmacro wanker::x
... (whatever:x ...) ...)

in other words, use the package system, shadow the symbol whose meaning
you want to change, and be explicit about the package of the original.

or use advice, if your implementation offers them.

#:Erik
--
religious cult update in light of new scientific discoveries:
"when we cannot go to the comet, the comet must come to us."

Barry Margolin

unread,
Apr 1, 1998, 3:00:00 AM4/1/98
to

In article <6frjfr$bds$1...@Masala.CC.UH.EDU>,

<wan...@exploited.barmy.army> wrote:
>I tried storing the original macro in a variable (setq v #'macro-name),
>but then I could not find out how to call it (a macro equivalent to
>funcall?). Also, I'm not sure if (setq v #'macro-name) is guaranteed
>to work on all implementations.

It isn't. I think you want:

(setq v (macro-function 'macro-name))

To call it, you use (funcall v <form> <env>). <env> should be the
&environment parameter to the macro.

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.

Marco Antoniotti

unread,
Apr 1, 1998, 3:00:00 AM4/1/98
to

Barry Margolin <bar...@bbnplanet.com> writes:

> In article <6frjfr$bds$1...@Masala.CC.UH.EDU>,
> <wan...@exploited.barmy.army> wrote:
> >I tried storing the original macro in a variable (setq v #'macro-name),
> >but then I could not find out how to call it (a macro equivalent to
> >funcall?). Also, I'm not sure if (setq v #'macro-name) is guaranteed
> >to work on all implementations.
>
> It isn't. I think you want:
>
> (setq v (macro-function 'macro-name))
>
> To call it, you use (funcall v <form> <env>). <env> should be the
> &environment parameter to the macro.

Which, IIANM, can be portably set only to NIL.

Cheers

--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it

Kent M Pitman

unread,
Apr 1, 1998, 3:00:00 AM4/1/98
to

wan...@exploited.barmy.army writes:

> I would like to reimplement a built in macro and have my new
> implementation call the old one. For example, given macro x
> I would like to do something like:
>
> (defmacro x
> `(... call-old-x ...))

I recommend the following approach which is clean and is really the intended thing.
(I did not however -test- this code, because it was inconvenient to do so at the time
I was writing this message. Caveat emptor, or however that goes...)

;;; Redefine DOTIMES to permit RETURN but not GO.

(defpackage "MY-EXTENSIONS"
(:use "COMMON-LISP")
(:shadow "DOTIMES")
(:export "DOTIMES"))

(in-package "MY-EXTENSIONS")

(defmacro dotimes ((var initform &rest maybe-resultform) &rest body)
(let ((decls '())))
(loop (unless (and body (consp (car body)) (eq (caar body) 'declare))
(return))
(push (pop body) decls))
(setq decls (nreverse decls))
`(common-lisp:dotimes (,var ,initform ,@maybe-resultform)
,@decls
(progn ;mask the implicit tagbody supplied by cl:dotimes
,@body)))

(defpackage "FOO"
(:use "COMMON-LISP" "MY-EXTENSIONS")
(:shadowing-import-from "MY-EXTENSIONS" "DOTIMES") ;avoid symbol conflict
; since both CL and MY-EXTENSIONS export DOTIMES
);egakcapfed

(in-package "FOO")

(defun foo5 ()
(dotimes (i 5)
i ; ignored <-- relies on FOO::DOTIMES making this a variable, not a go tag
(print 'foo)))


- - - - -

The point is that if you using shadowing, you can produce equivalent packages
of code without actually "redefining" system macros. The old one has a name
and the new one has a name, and everyone who wants either of them can conveniently
access the one they want without clashing.

Marco Antoniotti

unread,
Apr 1, 1998, 3:00:00 AM4/1/98
to

Kent M Pitman <pit...@world.std.com> writes:

>
> (defpackage "MY-EXTENSIONS"
> (:use "COMMON-LISP")
> (:shadow "DOTIMES")
> (:export "DOTIMES"))
>
> (in-package "MY-EXTENSIONS")
>

As an aside, I see also that using strings in package related
functions and macros for package names and symbol names is a *good*
thing.

Erik Naggum

unread,
Apr 1, 1998, 3:00:00 AM4/1/98
to

* Marco Antoniotti

| As an aside, I see also that using strings in package related functions
| and macros for package names and symbol names is a *good* thing.

uhm? why? using strings interferes with case massaging in the Lisp
reader. the only advantage is that no new symbols are created, but using
uninterned symbols or keywords (for package names) isn't _that_ much
trouble, is it?

Kent M Pitman

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

Erik Naggum <cle...@naggum.no> writes:

> * Marco Antoniotti
> | As an aside, I see also that using strings in package related functions
> | and macros for package names and symbol names is a *good* thing.
>
> uhm? why? using strings interferes with case massaging in the Lisp
> reader. the only advantage is that no new symbols are created, but using
> uninterned symbols or keywords (for package names) isn't _that_ much
> trouble, is it?

Marco is right, IMO. Because of introspective operations (like INTERN,
DO-SYMBOLS, etc.) programs can detect a symbol and therefore can be affected
by a symbol which they do not directly refer to. This is a serious barrier
to a GC trying to dump out a trim application. When you name symbols in a
DEFPACKAGE with symbol names, you intern them, and then later it's hard to
guess why they were interned--was it only for a momentary help in changing
the case the user was too lazy to change, or for some material reason?
Often a Lisp system contains a tree-shaker option that says to just remove
such symbols blindly, but such a heuristic is nothing more than a heuristic
and is, IMO, bad style to use. Consequently, better not to make the garbage
in the first place.

It is a religious matter at some level, since some just don't care if
that stuff gets GC'd and some don't mind telling the system to blindly
GC. Perhaps it's just too small an issue to care about. But the side
of Empirically Observable Right is technically on my side on this one,
I think, Erik.

Actually, an area I've started to recently feel worse about is the use
of keyword symbols as slot initargs, etc. When one does:

(defclass foo ()
((width :initarg :width :accessor width)))

I'm starting to feel like we're building up a LOT of symbols like :WIDTH
here that are utterly gratuitous, all so we can say
(make-instance 'foo :width 3)
instead of
(make-instance 'foo 'width 3)
ok, and admittedly sometimes
(make-instance 'fred:foo 'fred:width 3)
or even
(make-instance 'fred:foo 'bill:width 3)
if it's an inherited symbol that is not re-exported (which would be
unusual, I think). But the fact is that we deliberately go out of our
way to (a) create a possible package collision and (b) almost double the
number of symbols in the class system (if you assume the number of named
slots far exceeds the number of named classes and so dwarfs other quantities).

Then again, one of the things that has traditionally been a Lisp strength
is that one just learns not to care about such small issues, not because
they don't add up, but because they only ever amount to constant factors.
And it is the willingness to disregard constant factors in the result that
gives Lisp its never-tabulated but still-believed-large leg up in speed of
appliction development over some other languages, keeping the programmer
focused on the domain problem and not the implementation details, which
can drive any programmer mad.

So just ignore me.

Marco Antoniotti

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

Erik Naggum <cle...@naggum.no> writes:

> * Marco Antoniotti
> | As an aside, I see also that using strings in package related functions
> | and macros for package names and symbol names is a *good* thing.
>
> uhm? why? using strings interferes with case massaging in the Lisp
> reader. the only advantage is that no new symbols are created, but using
> uninterned symbols or keywords (for package names) isn't _that_ much
> trouble, is it?

I do not remember what the HyperSpec says about case massaging,
however, CLtL[12] kind of assumes that symbol names are always
converted to uppercase.

It is not that much more trouble to use uninterned symbols or keywords
for package names and listed symbols.

It is just a matter of style and of saving symbols.

Tim Bradshaw

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

* Erik Naggum wrote:
> uhm? why? using strings interferes with case massaging in the Lisp
> reader. the only advantage is that no new symbols are created, but using
> uninterned symbols or keywords (for package names) isn't _that_ much
> trouble, is it?

Well if you *don't* use strings or uninterned symbols then you're
likely to lose horribly at some point because you may not know enough
about the state of the package system (in particular what the current
package is when you define a package) to avoid interning symbols at
read time in packages in which it not be a good thing to intern them
(especially for things you're exporting from the package being
defined).

(The case that caused me to start using strings was where I had a
package definition which did (:export a b c ...), where I wanted later
to use that package from CL-USER.)

I suppose you could religiously use uninterned symbols (or keywords
perhaps) but that always looks pretty grotesque to me...

--tim

Espen Vestre

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

Tim Bradshaw <t...@aiai.ed.ac.uk> writes:

> I suppose you could religiously use uninterned symbols (or keywords
> perhaps) but that always looks pretty grotesque to me...

I always use keywords - probably because they look _prettier_ to me!

--

espen

Erik Naggum

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

* Marco Antoniotti
| As an aside, I see also that using strings in package related functions
| and macros for package names and symbol names is a *good* thing.

* Erik Naggum


| uhm? why? using strings interferes with case massaging in the Lisp
| reader. the only advantage is that no new symbols are created, but using
| uninterned symbols or keywords (for package names) isn't _that_ much
| trouble, is it?

thanks to Kent Pitman, Marco Antoniotti, and Tim Bradshaw for their
comments. the reason for my concern is a little involved, so let me
explain. I use Franz Inc's Allegro Common Lisp and it has a feature,
called the "case mode", whereby symbols names may be downcased. (this
also makes APROPOS a lot easier to use.) the reason I switched to use
"case-sensitive-lower" (as it is called) as the preferred case was that
the Lisp printer in ACL doesn't quite follow the specification when
*PRINT-CASE* and READTABLE-CASE settings differ from the defaults, and I
really don't want to read symbol names in all caps (except in prose text
where they are meant to stand out). therefore, I also switched to using
uninterned symbols in DEFPACKAGE. I agree with Tim that it has a certain
grotesque flavor to it, but I saw it as better than the name conflicts
that would follow from using the wrong case when "hard-wiring" the case
of symbols names. however, upon thinking a bit more about this, spurred
by the comments I received, I have returned to "case-insensitive-upper"
as the preferred case mode and switched to using strings in DEFPACKAGE
and other such forms. thanks, guys. *PRINT-CASE* is :DOWNCASE. I'll
see if I can unlearn the habit of using APROPOS on lower-case strings.

#:Erik
--
(defmacro pretty-loop (&rest parenthesized-forms)
"Make the dream that each LOOP clause be parenthesized come true."
`(loop ,@(apply #'append parenthesized-forms)))

Jason Trenouth

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

On 02 Apr 1998 10:34:37 +0000, Erik Naggum <cle...@naggum.no> wrote:

> I'll see if I can unlearn the habit of using APROPOS on lower-case strings.

LispWorks' APROPOS is case insensitive for this very reason.

__Jason

Espen Vestre

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

Erik Naggum <cle...@naggum.no> writes:

> and other such forms. thanks, guys. *PRINT-CASE* is :DOWNCASE. I'll


> see if I can unlearn the habit of using APROPOS on lower-case strings.

I'll probably be accused of severe misuse of the keyword package,
but I still can't resist mentioning that I use keywords as parameters
to apropos as well...

--

(espen vestre)

P. Srinivas

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

Jason Trenouth (ja...@harlequin.com) wrote:
: On 02 Apr 1998 10:34:37 +0000, Erik Naggum <cle...@naggum.no> wrote:

: > I'll see if I can unlearn the habit of using APROPOS on
: > lower-case strings.

: LispWorks' APROPOS is case insensitive for this very reason.

How about using symbol as an argument for APROPOS? This adds one extra
symbol for each call to APROPOS, but does take care of the case
problem.


Srini
--------------------
Srinivas Palthepu Email: sr...@cs.usask.ca
ARIES laboratory, Phones: (306) 966-8654 (lab)
Department of Computer Science, (306) 966-4759 (office)
University of Saskatchewan, (306) 373-6724 (home)
57 Campus Dr, Saskatoon, SK, S7N 5A9 Fax: (306) 966-4884

Steven D. Majewski

unread,
Apr 2, 1998, 3:00:00 AM4/2/98
to

Glad to see this topic come up --
I thought I was the only one to worry about this.

I used strings until I ran into some problems with case consistency
with REQUIRE, PROVIDE and how they were stored in *modules*.

Then, I switched to using symbols, so I didn't have to worry about
whether the various files were case consistent.

Then I ran into problems with packages and shadowing symbols from
when some of those symbols got interned. ( Plus, I still had to
make sure the code consistently used symbols. )

Then I switched back to strings and tried to check that they were
all case consistent.

I never though to try keywords -- that sounds like it gets around
both problems. ( In other cases, I've found that leaning towards
using keyword symbols where possible ( or explicit packages in
other cases ) has helped to avoid unpleasant surprises when
EQ tests are done on symbols in different packages.


---| Steven D. Majewski (804-982-0831) <sd...@Virginia.EDU> |---
---| Department of Molecular Physiology and Biological Physics |---
---| University of Virginia Health Sciences Center |---
---| P.O. Box 10011 Charlottesville, VA 22906-0011 |---
"Nature and Nature's laws lay hid in night:
God said, let Newton be! and all was light." - pope


0 new messages