defmacro question

40 views
Skip to first unread message

John Clonts

unread,
Jul 25, 2000, 3:00:00 AM7/25/00
to
I am trying to make a macro which will defun a function whose name is
constructed from a macro parameter, e.g.

(define-struct person (name))
--> defuns a function called make-person

(make-person "joe")

Here is my attempt so far:

(defmacro define-struct (nm)
; (defun make-'nm' () "hello")
(list
'defun
(symbol-function
(make-symbol (stringappend "make-" (symbol-name nm))))
'()
"hello"))

(defun stringappend (&rest lst)
(apply #'concatenate 'string "" lst))

But the problem for now is that the (symbol-function ....) expression
result is apparently not suitable for the defun.

Perhaps a related confusion is: What is the difference between 'foo and
:foo

(eq (type-of 'foo)(type-of :foo)) ==> T
(eq 'foo :foo) ==>NIL
(eql 'foo :foo) ==>NIL
(equal 'foo :foo) ==>NIL

(I think I understand that (eq #'foo (symbol-function 'foo)))

(As you can imagine I am coming from Scheme. I am using at the moment
Corman Lisp.

Thank you for any help you can offer :)

John

Sent via Deja.com http://www.deja.com/
Before you buy.

John Clonts

unread,
Jul 25, 2000, 3:00:00 AM7/25/00
to
Rainer Joswig wrote:
>
> In article <8ll4hf$cbd$1...@nnrp1.deja.com>, John Clonts

> <joh...@my-deja.com> wrote:
>
> > I am trying to make a macro which will defun a function whose name is
> > constructed from a macro parameter, e.g.
> >
> > (define-struct person (name))
> > --> defuns a function called make-person
> >
> > (make-person "joe")
> >
> > Here is my attempt so far:
> >
> > (defmacro define-struct (nm)
> > ; (defun make-'nm' () "hello")
> > (list
> > 'defun
> > (symbol-function
> > (make-symbol (stringappend "make-" (symbol-name nm))))
> > '()
> > "hello"))
>
> (defmacro define-struct (name)
> `(defun ,(intern (concatenate 'string "MAKE-" (symbol-name name)))
> ()
> "hello"))
>
> ? (macroexpand-1 '(define-struct foo))
>
> -> (DEFUN MAKE-FOO () "hello")
>
> Or:
>
> (defmacro define-struct (name)
> (list 'defun
> (intern (concatenate 'string "MAKE-" (symbol-name name)))
> '()
> "hello"))

Thank you very much! It was just the 'intern' that I was missing. I
will try and figure out why (make-symbol) makes something different than
(intern) and thats also different than just 'symbol, and of cours
#'func-symbol. (whew!)

Cheers,
John

John Clonts

unread,
Jul 25, 2000, 3:00:00 AM7/25/00
to
Martti Halminen wrote:

>
> John Clonts wrote:
> >
> > I am trying to make a macro which will defun a function whose name is
> > constructed from a macro parameter, e.g.
> >
> > (define-struct person (name))
> > --> defuns a function called make-person
>
> Your choice of names is a little misleading: Common Lisp already
> has defstruct, which as one of its effects creates a constructor
> function (or was it method? I don't remember offhand) with a
> make- -style name, so there is a risk that somebody reading your
> code could get mixed up on which function you are talking about.
>

Thanks, but all that is beside the point in my case-- I'm just trying to
figure how the macros work.

> > (make-person "joe")
> >
> > Here is my attempt so far:
> >
> > (defmacro define-struct (nm)
> > ; (defun make-'nm' () "hello")
> > (list
> > 'defun
> > (symbol-function
> > (make-symbol (stringappend "make-" (symbol-name nm))))
> > '()
> > "hello"))
>

> - you could also use backquote to make your macros more readable
>

gotcha. 6 vs half-dozen.

> - what are you trying to achieve with calling symbol-function?
> That returns a function object, normally defun is used with a
> symbol as its first parameter.
>

e.g. if the name passed in is 'balloon, I want the result function to be
called make-balloon.

> - intern might be better than make-symbol in this case
>

This is the solution I am seeking, thanks! (And to Mr. Joswig)

> - you'll also get interesting results with mixed-case names,
> remember that CL usually converts symbol names to uppercase when
> reading them.

Ok, I'll keep that in mind.

>
> > Perhaps a related confusion is: What is the difference between 'foo and
> > :foo
>

> 'foo -> the symbol FOO in the current package
>
> :foo -> the symbol FOO in the keyword package
>
> --

Thanks!

John

Rainer Joswig

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
In article <8ll4hf$cbd$1...@nnrp1.deja.com>, John Clonts
<joh...@my-deja.com> wrote:

> I am trying to make a macro which will defun a function whose name is
> constructed from a macro parameter, e.g.
>
> (define-struct person (name))
> --> defuns a function called make-person
>

> (make-person "joe")
>
> Here is my attempt so far:
>
> (defmacro define-struct (nm)
> ; (defun make-'nm' () "hello")
> (list
> 'defun
> (symbol-function
> (make-symbol (stringappend "make-" (symbol-name nm))))
> '()
> "hello"))

(defmacro define-struct (name)
`(defun ,(intern (concatenate 'string "MAKE-" (symbol-name name)))
()
"hello"))

? (macroexpand-1 '(define-struct foo))

-> (DEFUN MAKE-FOO () "hello")

Or:

(defmacro define-struct (name)
(list 'defun
(intern (concatenate 'string "MAKE-" (symbol-name name)))
'()
"hello"))

--
Rainer Joswig, BU Partner,
ISION Internet AG, Steinhöft 9, 20459 Hamburg, Germany
Tel: +49 40 3070 2950, Fax: +49 40 3070 2999
Email: mailto:rainer...@ision.net WWW: http://www.ision.net/

Martti Halminen

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
John Clonts wrote:
>
> I am trying to make a macro which will defun a function whose name is
> constructed from a macro parameter, e.g.
>
> (define-struct person (name))
> --> defuns a function called make-person

Your choice of names is a little misleading: Common Lisp already


has defstruct, which as one of its effects creates a constructor
function (or was it method? I don't remember offhand) with a
make- -style name, so there is a risk that somebody reading your
code could get mixed up on which function you are talking about.

> (make-person "joe")


>
> Here is my attempt so far:
>
> (defmacro define-struct (nm)
> ; (defun make-'nm' () "hello")
> (list
> 'defun
> (symbol-function
> (make-symbol (stringappend "make-" (symbol-name nm))))
> '()
> "hello"))

- you could also use backquote to make your macros more readable

- what are you trying to achieve with calling symbol-function?


That returns a function object, normally defun is used with a
symbol as its first parameter.

- intern might be better than make-symbol in this case

- you'll also get interesting results with mixed-case names,


remember that CL usually converts symbol names to uppercase when
reading them.

> Perhaps a related confusion is: What is the difference between 'foo and

Barry Margolin

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
In article <397E51AB...@mastnet.net>,

John Clonts <jcl...@mastnet.net> wrote:
>Thank you very much! It was just the 'intern' that I was missing. I
>will try and figure out why (make-symbol) makes something different than
>(intern) and thats also different than just 'symbol, and of cours
>#'func-symbol. (whew!)

MAKE-SYMBOL and INTERN both create symbols. The latter also interns the
symbol it created; if a symbol isn't interned, you won't be able to access
it by typing its name.

#'func-symbol evaluates to the function that FUNC-SYMBOL is bound to.
Since DEFUN requires its first parameter to be a function name, not a
function object, it makes no sense to put that in the macro expansion.

--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, 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.

Thomas A. Russ

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
John Clonts <joh...@my-deja.com> writes:


> I am trying to make a macro which will defun a function whose name is
> constructed from a macro parameter, e.g.
>
> (define-struct person (name))
> --> defuns a function called make-person
>

> (make-person "joe")
>
> Here is my attempt so far:
>
> (defmacro define-struct (nm)
> ; (defun make-'nm' () "hello")
> (list
> 'defun
> (symbol-function
> (make-symbol (stringappend "make-" (symbol-name nm))))
> '()
> "hello"))
>

> (defun stringappend (&rest lst)
> (apply #'concatenate 'string "" lst))
>
> But the problem for now is that the (symbol-function ....) expression
> result is apparently not suitable for the defun.

Correct in your analysis. Defun wants to have a symbol as the second
element of its list. Defun itself takes care of setting the
SYMBOL-FUNCTION slot of the symbol, so in normal everyday Common Lisp
work you don't actually use this. (Nor SYMBOL-VALUE either). I realize
that coming from Scheme having the separate value and function
namespaces may be a little more complicated, but it's not as bad as you
are making it.

Anyway, you most likely don't want to use MAKE-SYMBOL, since that
creates an uninterned symbol. You want to use INTERN instead. The
problem with an uninterned symbol is that you can't reference it by
name, only by keeping a binding to it. INTERN creates a symbol (if
necessary) and stores an association between the symbol name and the
symbol object. This association is stored in a data structure called a
package (of which there are several in lisp -- see below for an example)
so that the reader can map symbol names to symbol objects.

Another issue to be aware of is that the reader normally converts input
into uppercase:

(symbol-name 'foo) => "FOO"

but make-symbol and intern do not:

(symbol-name (intern "foo")) => "foo"

so if you concatenate the string "make-" to the symbol name of 'FOO you
would end up with a symbol that will most likely print as:

|make-FOO|

which is distinct from the symbol 'make-foo (which is the same as the
symbol 'MAKE-FOO). You would then need to reference your created
function as:

(|make-FOO| ...)

Of course, if you uppercase the string, then it wouldn't be a problem.

What can also help you in debugging macros is the use of the MACROEXPAND
and MACROEXPAND-1 functions, which will show you what the macro expands
into. Together with the pretty printer PPRINT, you can see what the
system is doing.

BTW, if you want to get serious about writing macros, it would save you
lots of effort and frustration to learn the backquote syntax. This
allows a much clearer (to me at least) view of what kinds of structures
you are creating, since you don't have all those calls to LIST
cluttering things up.

Normally the way I write a macro is to start with the end result, namely
the form I want to have the macro produce, and then I backquote it and
then add commas to the variable parts of the structure. (Then I worry
about variable capture and multiple evaluation of arguments and fix
those up).

> Perhaps a related confusion is: What is the difference between 'foo and
> :foo

Try:

(symbol-package 'foo)
(symbol-package :foo)

--
Thomas A. Russ, USC/Information Sciences Institute t...@isi.edu

Erik Naggum

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
* Rainer Joswig <rainer...@ision.net>

| (defmacro define-struct (name)
| `(defun ,(intern (concatenate 'string "MAKE-" (symbol-name name)))
| ()
| "hello"))

To avoid exposing the case-ness of symbols, I prefer (symbol-name 'make-).

#:Erik
--
If this is not what you expected, please alter your expectations.

Rainer Joswig

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
In article <31736142...@naggum.net>, Erik Naggum <er...@naggum.net>
wrote:

> * Rainer Joswig <rainer...@ision.net>
> | (defmacro define-struct (name)
> | `(defun ,(intern (concatenate 'string "MAKE-" (symbol-name name)))
> | ()
> | "hello"))
>
> To avoid exposing the case-ness of symbols, I prefer (symbol-name 'make-).


One can use it that way - usually I use strings, because I don't
want to create arbitrary symbols in a package. For example
I'll always write (in-package "FOO") and never
(in-package 'foo). I also really *want* to specify the case-ness
of a symbol.

Erik Naggum

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to
* Rainer Joswig <rainer...@ision.net>

| One can use it that way - usually I use strings, because I don't
| want to create arbitrary symbols in a package.

You can limit the effect to compile-time with #.(symbol-name 'x).

| For example I'll always write (in-package "FOO") and never
| (in-package 'foo).

I use (in-package :foo).

| I also really *want* to specify the case-ness of a symbol.

I have a cat, so I know that when she digs her very sharp claws into
my chest or stomach it's really a sign of affection, but I don't see
any reason for programming languages to show affection with pain.

Steven M. Haflich

unread,
Jul 26, 2000, 3:00:00 AM7/26/00
to

Erik Naggum wrote:
>
> * Rainer Joswig <rainer...@ision.net>
> | One can use it that way - usually I use strings, because I don't
> | want to create arbitrary symbols in a package.
>
> You can limit the effect to compile-time with #.(symbol-name 'x).
>
> | For example I'll always write (in-package "FOO") and never
> | (in-package 'foo).
>
> I use (in-package :foo).

You can get both benefits this way:

(in-package #:foo)

It is tedious, but less tedious than the compile-time symbol-name.

Erik Naggum

unread,
Jul 27, 2000, 3:00:00 AM7/27/00
to
* "Steven M. Haflich" <haf...@pacbell.net>

| It is tedious, but less tedious than the compile-time symbol-name.

concatenate doesn't accept string designators. in-package does.

Kent M Pitman

unread,
Jul 28, 2000, 3:00:00 AM7/28/00
to
"Steven M. Haflich" <haf...@pacbell.net> writes:

> Erik Naggum wrote:
> >
> > * Rainer Joswig <rainer...@ision.net>
> > | One can use it that way - usually I use strings, because I don't
> > | want to create arbitrary symbols in a package.
> >
> > You can limit the effect to compile-time with #.(symbol-name 'x).
> >
> > | For example I'll always write (in-package "FOO") and never
> > | (in-package 'foo).
> >
> > I use (in-package :foo).
>
> You can get both benefits this way:
>
> (in-package #:foo)
>

> It is tedious, but less tedious than the compile-time symbol-name.

(in-package #:foo) has the problem that #:foo does not self-evaluate.
The reason people like "FOO" and :FOO is that they are cltl1-compatible.

Personally, I always use

(in-package #.(load-time-value (setf (symbol-value '#1=#:foo) '#1#)))

because it has the benefits of Erik's version and smh's version combined.
That is, it both doesn't expose symbol case and it's backward compatible
to cltl1 and it gets gc'd quickly.

Heh.

Just kidding.

I rather like (in-package "FOO") because I think it's good for people to
be reminded periodically that package names are conventionally uppercase,
and also because I like the idea that literal constants stand out from code.
But that's probably just because I'm getting old and haven't grown up on
full-color text editors to show me distinctions between code and constants.

Reply all
Reply to author
Forward
0 new messages