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
* 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."
<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.
Barry Margolin <bar...@bbnplanet.com> writes: > In article <6frjfr$bd...@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.
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...)
(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 | 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?
#:Erik -- religious cult update in light of new scientific discoveries: "when we cannot go to the comet, the comet must come to us."
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:
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.
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.
* 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 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!
* 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)))
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...
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