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

newbie Lisp question

16 views
Skip to first unread message

nick...@ptcstudios.com

unread,
Mar 8, 2000, 3:00:00 AM3/8/00
to

I am trying to make a macro which creates functions, but I do not know
how to create a the symbol to be used in the expanded code.

Example:

( defmacro defMyHashThing (name)
`(defun make-,name () (make-hash-table)))

When I run macroexpand on this I get:

: (macroexpand-1 '(defMyHashThing foo))

(DEFUN MAKE- FOO NIL (MAKE-HASH-TABLE))

Note that a space is inserted between "make-" and "foo". The macro
will not put the "make-" and the "foo" together, so only a function
called "make-" is defined when the macro is evaluated.

Thanks.

nick...@ptcstudios.com

Barry Margolin

unread,
Mar 8, 2000, 3:00:00 AM3/8/00
to
In article <6dDGOGLUjzLw8C...@4ax.com>,

You have to create a symbol, using MAKE-SYMBOl or INTERN.

(defmacro defMyHashThing (name)
`(defun ,(intern (concatenate 'string "MAKE-" name)) ()
(make-hash-table)))

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, 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.

Pierre R. Mai

unread,
Mar 8, 2000, 3:00:00 AM3/8/00
to
nick...@ptcstudios.com writes:

> I am trying to make a macro which creates functions, but I do not know
> how to create a the symbol to be used in the expanded code.
>
> Example:
>
> ( defmacro defMyHashThing (name)
> `(defun make-,name () (make-hash-table)))

(defmacro defmyhashthing (name)
(let* ((fun-name (concatenate 'string "MAKE-" (symbol-name name)))
(fun-sym (intern fun-name (symbol-package name))))
`(defun ,fun-sym () (make-hash-table))))

Backquote only works for putting together lists, it doesn't know
anything about symbols or other data-structures.

The code to create the proper symbol is a bit complicated, because you
need to do two things:

a) Create a symbol named "MAKE-FOO" out of "MAKE-" and "FOO", that is
b) interned in the package that the original name symbol came from.

The second part is important, because you want

(in-package :BAR)

(defmyhashthing baz::foo)

to create baz::make-foo and not bar::make-foo.

Regs, Pierre.

--
Pierre Mai <pm...@acm.org> PGP and GPG keys at your nearest Keyserver
"One smaller motivation which, in part, stems from altruism is Microsoft-
bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]

Tim Bradshaw

unread,
Mar 8, 2000, 3:00:00 AM3/8/00
to
* nicknews wrote:

> ( defmacro defMyHashThing (name)
> `(defun make-,name () (make-hash-table)))

You want something like:

`(defun ,(intern (format nil "~A-~A"
(symbol-name :make)
(symbol-name name))) ...)

The deviousness with symbol-name is an attempt to prevent either the common
problem of:

(intern (format nil "~A-~A" :make name))

which doesn't do what you probably want if *print-case* is :downcase,
or the more obscure problem (perhaps never a problem in ANSI CL):

(intern (format nil "MAKE-~A" (symbol-name name)))

which will do something unexpected in Allegro in case-sensitive-lower mode.

I'm not sure this works in *all* cases, though I think it does.

--tim

Robert Monfera

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to

Pierre R. Mai wrote:

> (defmacro defmyhashthing (name)
> (let* ((fun-name (concatenate 'string "MAKE-" (symbol-name name)))
> (fun-sym (intern fun-name (symbol-package name))))
> `(defun ,fun-sym () (make-hash-table))))

When is it encouraged to put together symbol names though? By default,
DEFSTRUCT produces a host of functions with glued names, but it isn't
common in CL. For example, CLOS just uses MAKE-INSTANCE (OK, it's a GF
anyway) and TYPEP. A reason is that such glueing benefits humans only
and does not benefit code walkers and other tools, and the benefit is
little if any.

Is it an indication that automagical function (or whatever) creation
with glued names is rarely encouraged? Any examples when it's the best
way of achieving something other than system integration?

Robert

Tim Bradshaw

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to
* Robert Monfera wrote:

> Is it an indication that automagical function (or whatever) creation
> with glued names is rarely encouraged? Any examples when it's the best
> way of achieving something other than system integration?

Whenever you want a bunch of accessor-type names, or a bunch of
functions with related names it's a good thing.

For instance CLIM has `spread` and `nospread' versions of a whole load
of things, with names like DRAW-LINE (takes arguments which are point
objects) and DRAW-LINE* (takes x, y pairs). These are generated from
the same macro (which I think may actually generate some other
definitions as well while it's at it).

I guess you might consider that system integration though?

--tim

Erik Naggum

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to
* Pierre R. Mai

| Backquote only works for putting together lists, it doesn't know
| anything about symbols or other data-structures.

backquote works on sequences, which includes vectors and lists.

#:Erik

Erik Naggum

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to
* Robert Monfera <mon...@fisec.com>

| When is it encouraged to put together symbol names though? By default,
| DEFSTRUCT produces a host of functions with glued names, but it isn't
| common in CL.
|
| Is it an indication that automagical function (or whatever) creation with
| glued names is rarely encouraged? Any examples when it's the best way of
| achieving something other than system integration?

recently, I wrote that making some concepts hard to express didn't cause
people to suffer from having to express them, but made the concepts
suffer because they would be underutilized. humans, falling prey to the
siren song of convenience, will always think this way. therefore, the
languages we use must make smart concepts convenient to express and dumb
concepts inconvenient to express. the natural tendency is the opposite.

(intern (concatenate 'string (symbol-name #:make-) (symbol-name symbol))
(symbol-package symbol))

will return a new symbol prefixed with "make-" in the same package as the
symbol without the prefix (thanks for that careful bit, Pierre), but is
this hard to read? is it a lot of "internal stuff" that people shouldn't
ned to worry about? I dont' think so. I think this is the smallest you
can do, short of writing a function specifically to glue symbol names
that does all this, but think about its hypothetical interface for a
second: it would naturally want two symbols, but which one is prefix and
which one is suffix? (resist the temptation to search for the hyphen!)
so either you get two functions or you supply the package separately, or
perhaps you think you could supply one string and one symbol, but either
way, you have caused the user of your function to exercise a lot more
brainpower on your symbol-glue function than on the expression above,
which should be a no-brainer for an experienced Common Lisp programmer in
a way the symbol-glue functions wouldn't be because they are infrequently
used. and if they aren't infrequently used, we're back to Robert's
question: should we encourage this? I don't think we should, either, so
it would be bad if it were too convenient to do it.

FORMAT is clearly in the "too convenient" camp, since it makes doing it
the wrong way so convenient, and burdens the user with case conversion
issues in the reader and the printer at the same time.

but consider a More Common Lisp that does no case conversion in the
reader or the printer (which is more common than doing it, hence my
punnish name), with what-you-see-is-what-you-get symbol names:

(intern (format nil "make-~a" symbol) (symbol-package symbol))

consider all the idiomatic stuff we got rid of: either an uninterned or
keyword symbol just to get the symbol name right or an upper-case prefix
string literal, and extracting the symbol-name part. this idiomatic
burden is a no-brainer to an experienced Common Lisp programmer, but
_acquiring_ the expertise so it becomes a no-brainer is not effortless at
all, and probably involves struggling and lots of confusion until the
full ramifications of Common Lisp's attitude to case are internalized.

so instead of encouraging the convenient creation of symbols, we have an
elaborate scheme to discourage people from looking at symbol names and
only use the symbols as symbols, but this works directly against the work
needed to acquire the expertise in using them correctly! since symbols
is very powerful abstraction mechanism, and case conversion is also a
very powerful mechanism in human communication (it has definite value,
but by informed choice, not default), we've forced ourselves out on a
limb every time we have to deal with them, and some are worrying that any
proposal to fix this is akin to cutting the limb on the dumb side. this
is a case of making a smart concept cumbersome to express, and forces us
to consider more convenient options merely for the sake of convenience --
it should have been _sufficiently_ convenient to begin with not to have
to worry about case conversion details.

let's find a way to make Common Lisp work with readtable-case :preserve
and lower-case symbol names, so what-you-see-is-what-you-get-ness is also
preserved for experienced and novice programmer alike, and we can do
smart stuff without having to be too clever, too.

#:Erik

Axel Schairer

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to
pm...@acm.org (Pierre R. Mai) writes:
> The code to create the proper symbol is a bit complicated, because you
> need to do two things:
>
> a) Create a symbol named "MAKE-FOO" out of "MAKE-" and "FOO", that is
> b) interned in the package that the original name symbol came from.
>
> The second part is important, because you want
>
> (in-package :BAR)
>
> (defmyhashthing baz::foo)
>
> to create baz::make-foo and not bar::make-foo.

There is a problem with symbols used from other packages.

(defmyhashthing list)

interns MAKE-LIST in CL as an internal symbol (provided you use the CL
package). So sometimes you might want to have the symbol interned in
the current package. A more detailed explanation of this by Kent M
Pitman is at
http://x46.deja.com/getdoc.xp?AN=359498244&search=thread&CONTEXT=952603394.1921974274&HIT_CONTEXT=&HIT_NUM=&hitnum=2

Axel

Marco Antoniotti

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to

nick...@ptcstudios.com writes:

> I am trying to make a macro which creates functions, but I do not know
> how to create a the symbol to be used in the expanded code.
>
> Example:
>
> ( defmacro defMyHashThing (name)

^^^^^^^^^^^^^^

Please! No Java or C++ stuff here. def-my-hash-thing is way better :)

> `(defun make-,name () (make-hash-table)))
>
> When I run macroexpand on this I get:
>
> : (macroexpand-1 '(defMyHashThing foo))
>
> (DEFUN MAKE- FOO NIL (MAKE-HASH-TABLE))
>
> Note that a space is inserted between "make-" and "foo". The macro
> will not put the "make-" and the "foo" together, so only a function
> called "make-" is defined when the macro is evaluated.

You need to actually create a name for the function (i.e. you need to
create a symbol). This name is *not* a string. It is much more.
You need to do

(defmacro def-my-hash-thing (name)
(let ((make-name (intern (concatenate 'string "MAKE-"
(string name)))))
`(defun ,make-name () (make-hash-table))))

You may wornder why you need to do a thing which in Tcl you'd do
simply by concatenation.

The point is that in CL you are *not* using strings as your basic
structure, instead you use more sophisticated objects.

Cheers


--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa

Daniel Barlow

unread,
Mar 9, 2000, 3:00:00 AM3/9/00
to
Marco Antoniotti <mar...@parades.rm.cnr.it> writes:

> nick...@ptcstudios.com writes:
> > ( defmacro defMyHashThing (name)
> ^^^^^^^^^^^^^^
>
> Please! No Java or C++ stuff here. def-my-hash-thing is way better :)

Perhaps define-my-hash-thing, even

I realise that this is a style issue, and thus religious. I mostly
attempt to follow the church of Pitman/Norvig as described in
http://www.norvig.com/luv-slides.ps, and most of the rest of this post
is merely to provide a context for recommending that anyone who hasn't
read it does so.

Page 98 of that document is the one to which I refer here:

| - Minimize abbreviations
|
| Most words have many possible abbreviations but only one correct
| spelling. Spell out names so that they are easier to read,
| remember, and find.


A completely tangential debate that we could have: they recommend
"verb-noun" function names rather than "noun-verb" -

frob-volume-control
call-cthulu

However, this doesn't really gel with, say, the PATHNAME functions, or
the accessors that defstruct generates, which are noun-verb. I more
or less standardized on noun-verb despite Norvig/Pitman, figuring that
it didn't really matter that much provided I was consistent.

cthulu-invoke
volume-control-frob
volume-control-set

-dan

Tim Bradshaw

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
* Daniel Barlow wrote:

> However, this doesn't really gel with, say, the PATHNAME functions, or
> the accessors that defstruct generates, which are noun-verb.

No they aren't, they're noun-noun compounds (pathname-directory, say
or foo-slot).

--tim

Tim Bradshaw

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
* Erik Naggum wrote:
> let's find a way to make Common Lisp work with readtable-case :preserve
> and lower-case symbol names, so what-you-see-is-what-you-get-ness is also
> preserved for experienced and novice programmer alike, and we can do
> smart stuff without having to be too clever, too.

It's certainly the case that making symbols from other symbols is one
of the classic CL `gotcha's -- I've seen code written by Lisp
programmers with much more experience than me which just gets this
wrong (I only found out because I habitually have my CL environments
print in lower-case).

So a CL with more obvious and flexible handling of case would clearly
be a good thing.

But I think that there *are* advantages to case-insensitive readers.
Specifically, case-sensitive languages seem to be vulnerable to the
drEadEd studlycaps vIrUs. C seems to be badly infected with this
despite having grown up with powerful Unix antibodies, and I think C++
was born with it (Java too I guess).

While I appreciate that CL probably does need to talk with these
infested languages, and thus presumably will in due course become
fully studly itself, I find the prospect sad.

--tim

--
tim bradshaw, ClEy limiTeD

Erik Naggum

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
* Tim Bradshaw <t...@cley.com>

| But I think that there *are* advantages to case-insensitive readers.
| Specifically, case-sensitive languages seem to be vulnerable to the
| drEadEd studlycaps vIrUs. C seems to be badly infected with this despite
| having grown up with powerful Unix antibodies, and I think C++ was born
| with it (Java too I guess).

the studlycaps infection is a serious issue. however, I think it grew
out of the stupid way symbols are constructed in some languages, with a
fixed set of characters available in symbol names and everything else
being "parsed" as operators and whatnot, causing people to get scared of
anything that looks like blank spaces. underscores, in particular, are
used much like "visible blanks", but they look so ugly it's no wonder
people don't use them. if you aren't afraid of what might look like an
operator, foo-bar-zot beats foo_bar_zot hands down any day, but if you
are afraid of operator look-alikes, you need fooBarZot to feel "safe".

| While I appreciate that CL probably does need to talk with these infested
| languages, and thus presumably will in due course become fully studly
| itself, I find the prospect sad.

I don't think this will happen, but I think it's _less_ likely to happen
with a lower-case Lisp than an upper-case Lisp. the reason may seem
counter-intuitive, but here goes: in an upper-case Lisp, getting symbols
right is just too difficult for mere mortals (more so when using anything
other than readtable-case :upcase), so to get them right, people resort
to various hacks, the _best_ of which is using strings to refer to the
foreign object and a symbol to hold onto the reference in the Lisp world,
but that's comparatively inconvenient, and the symbol won't be _created_
from the foreign name, for the obvious reasons. in a lower-case Lisp,
you _may_ use the symbol directly, but now it has disadvantages that you
can see, because they aren't overshadowed by the _disadvantages_ of
case-mangling in Common Lisp, so you can see the _advantages_ of using
strings to name foreign objects with funny names, _plus_ you get the
predictable results when you try to create the symbol-name yourself.
thus, an upcasing Lisp will present self-defeating inconveniences that
completely destroy the advantages of case-insensitivity, while a case-
preserving lower-case Lisp will present _encouragement_ to use the much
richer set of available symbol names, instead of the stupid names that
particularly Windowsized C++ use to look like mangled symbol names even
before the C++ mangler gets at them.

#:Erik

Rob Warnock

unread,
Mar 11, 2000, 3:00:00 AM3/11/00
to
Erik Naggum <er...@naggum.no> wrote:
+---------------
| * Tim Bradshaw <t...@cley.com>

| | While I appreciate that CL probably does need to talk with these infested
| | languages, and thus presumably will in due course become fully studly
| | itself, I find the prospect sad.
|
| I don't think this will happen, but I think it's _less_ likely to happen
| with a lower-case Lisp than an upper-case Lisp.
+---------------

That's been my experience with using a few implementations of Scheme
which are both [contrary to the standard] case-sensitive and lower-case
for all the built-in symbols. People still use hyphens instead of
underscore or studly caps. In fact, case is almost a non-issue *except*
when (1) interfacing to C code or (2) using "read" on external files
produced by some other program.


-Rob

-----
Rob Warnock, 41L-955 rp...@sgi.com
Applied Networking http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
1600 Amphitheatre Pkwy. PP-ASEL-IA
Mountain View, CA 94043

Tim Bradshaw

unread,
Mar 11, 2000, 3:00:00 AM3/11/00
to
* Rob Warnock wrote:

> That's been my experience with using a few implementations of Scheme
> which are both [contrary to the standard] case-sensitive and lower-case
> for all the built-in symbols. People still use hyphens instead of
> underscore or studly caps. In fact, case is almost a non-issue *except*
> when (1) interfacing to C code or (2) using "read" on external files
> produced by some other program.

I can think of two reasons for this. Firstly if there exist
effectively case-insensitive implementations to which you might want
to port you have a strong incentive to write in a sane way. Secondly
studliness seems to be a slow-developing disease -- the first C system
I saw that was seriously infected was X, although I'm sure there were
earlier ones.

More seriously, the point about hyphens warding it off is a pretty
good counterargument.

--tim

0 new messages