From: Stefan Nobis
Subject: Macros, Symbols and Strings
Date: 
Message-ID: <87y83khe5a.fsf@snobis.de>
Hi.

I try to understand when symbols are interned and what to do, if i
don't want symbols to stay interned.

Example:

(defmacro my-macro (param)
  `(symbol-name ',param))

(my-macro test)

In this case first TEST is not evaluated and not interned (at
macroexpansion time). When SYMBOL-NAME is called, TEST will be
interned. Right?

What do I have to do, if I don't want that symbol interned but get
the string? OK, i could just pass a string as parameter like in
(my-macro "test"). But say I would really like to call the macro
as in the first example without those quotation marks but I want
the effect of the second call, because I need a string
parameter. Is this a good solution:

(defmacro my-macro (param)
  `(progn
     (symbol-name ',param)
     (unintern ',param)))

-- 
Stefan.

From: JP Massar
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <0vmun15020tufahq840qkfcfaq1jb3m8js@4ax.com>
On Sat, 19 Nov 2005 16:05:05 +0100, Stefan Nobis <······@gmx.de>
wrote:

>Hi.
>
>I try to understand when symbols are interned and what to do, if i
>don't want symbols to stay interned.

A symbol is interned when the Lisp reader reads the symbol.
Interning has nothing to do with macroexpansion or compilation
or evaluation, except insofar as those processes might invoke
the Lisp reader.


>
>Example:
>
>(defmacro my-macro (param)
>  `(symbol-name ',param))
>
>(my-macro test)
>
>In this case first TEST is not evaluated and not interned (at
>macroexpansion time). When SYMBOL-NAME is called, TEST will be
>interned. Right?

Wrong.  TEST is interned when the reader reads what you typed
(or the reader reads the form in the file that is being loaded or
compiled)

>
>What do I have to do, if I don't want that symbol interned but get
>the string? OK, i could just pass a string as parameter like in
>(my-macro "test"). But say I would really like to call the macro
>as in the first example without those quotation marks but I want
>the effect of the second call, because I need a string
>parameter. Is this a good solution:

This (below) returns the result of UNINTERN as the result of the form
produced by the macro.  Probably not what you want.

>
>(defmacro my-macro (param)
>  `(progn
>     (symbol-name ',param)
>     (unintern ',param)))


Depending on exactly what you want:

;; This just returns the string

(defmacro my-macro (param)
  (prog1
    (symbol-name  param)
    (unintern param))

;; This returns a form which returns the string, computing it
;; from the(now)  uninterned symbol.  But that's just gross.

(defmacro my-macro (param)
  (prog1
    `(symbol-name  ',param)
    (unintern param))



I suspect that if you explained why you cared about these symbols
becoming uninterned someone could tell you why your concern
was misplaced.
From: Pascal Bourguignon
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <871x1c342h.fsf@thalassa.informatimago.com>
Stefan Nobis <······@gmx.de> writes:

> Hi.
>
> I try to understand when symbols are interned and what to do, if i
> don't want symbols to stay interned.
>
> Example:
>
> (defmacro my-macro (param)
>   `(symbol-name ',param))
>
> (my-macro test)
>
> In this case first TEST is not evaluated and not interned (at
> macroexpansion time). When SYMBOL-NAME is called, TEST will be
> interned. Right?
>
> What do I have to do, if I don't want that symbol interned but get
> the string? OK, i could just pass a string as parameter like in
> (my-macro "test"). But say I would really like to call the macro
> as in the first example without those quotation marks but I want
> the effect of the second call, because I need a string
> parameter. Is this a good solution:
>
> (defmacro my-macro (param)
>   `(progn  

Perhaps you mean prog1 here?

>      (symbol-name ',param)
>      (unintern ',param)))

As JP Massar explained, the symbols are interned when they're read.
You can use UNINTERN, what if:

(my-macro random-symbol-number-42) ; ok, new interned symbol, is uninterned.
(my-macro defun) ; oops, you unintern a useful symbol!


The trick is to avoid interning the symbols in the first place:

(my-macro #:my-own-symbol)
(my-macro #:defun)

The #: reader macro reads a symbol without interning it (calling
MAKE-SYMBOL instead of INTERN).

An intermediary trick is to use keywords:

(my-macro :my-own-symbol)
(my-macro :defun)

If you were using the symbol several times in the program, it would be
better to intern it in the KEYWORD package to avoid creating new
symbols with the same name over and over.

Of course,  in the case of  symbols used in DEFPACKAGE  for example, I
prefer  using strings  than uninterned  symbols, since  it's  the same
number of characters, and only the name is used anyways:

(defmacro my-macro (name)
   `(string ',name))

So you can write:
(my-macro "MY-SYMBOL") (my-macro #:MY-SYMBOL)
(my-macro "DEFUN")     (my-macro #:DEFUN)
to the same effect, or even:
(my-macro :MY-SYMBOL) (my-macro MY-SYMBOL)
(my-macro :DEFUN)     (my-macro DEFUN)
if you don't mind the interning.




-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You're always typing.
Well, let's see you ignore my
sitting on your hands.
From: Stefan Nobis
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <877jb4jvwj.fsf@snobis.de>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Of course,  in the case of  symbols used in DEFPACKAGE  for example, I
> prefer  using strings  than uninterned  symbols, since  it's  the same
> number of characters, and only the name is used anyways:

> (defmacro my-macro (name)
>    `(string ',name))

Ok, to get this right:

If I use "(my-macro foo)" the reader reads the code and does the
macroexpansion. When exactly is foo interned? At the moment the
reader reads the form? So in this case interning could not be
avoided by the macro and unintern is the (only?) way the get rid
of the interned symbol?

BTW: Is a complete symbol created (and interned) everytime the
reader reads a new unknown word? Does the reader call intern for
each new word read?

Why this all bothers me: I thought about defining some
commands. The syntax should look like defun but command and
(compiled) code to be executed is put in a hashtable, so I don't
need the interned symbols and I don't want to pollute the
namespace. Until now I'm fine with using strings like in

  (defcmd "name" (params) ...)

and it's not overly important, but I noticed that I don't quite
understand everything about names, symbols, strings and interning,
so I'm just curious.

-- 
Stefan.
From: Pascal Bourguignon
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <87d5kw1chq.fsf@thalassa.informatimago.com>
Stefan Nobis <······@gmx.de> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> Of course,  in the case of  symbols used in DEFPACKAGE  for example, I
>> prefer  using strings  than uninterned  symbols, since  it's  the same
>> number of characters, and only the name is used anyways:
>
>> (defmacro my-macro (name)
>>    `(string ',name))
>
> Ok, to get this right:
>
> If I use "(my-macro foo)" the reader reads the code and does the
> macroexpansion. When exactly is foo interned? At the moment the
> reader reads the form? So in this case interning could not be
> avoided by the macro and unintern is the (only?) way the get rid
> of the interned symbol?
>
> BTW: Is a complete symbol created (and interned) everytime the
> reader reads a new unknown word? Does the reader call intern for
> each new word read?

No. It calls INTERN for ALL the words!

When you type:

(defmacro my-macro (name) `(string ',name))
(my-macro foo)

it calls:

(INTERN "DEFMACRO") --> DEFMACRO ; :INHERITED
(INTERN "MY-MACRO") --> MY-MACRO ; NIL
(INTERN "NAME")     --> NAME ;     NIL
(INTERN "STRING")   --> STRING ;   :INHERITED
(INTERN "NAME")     --> NAME ;     :INTERNAL
(INTERN "MY-MACRO") --> MY-MACRO ; :INTERNAL
(INTERN "FOO")      --> FOO ;      NIL


> Why this all bothers me: I thought about defining some
> commands. The syntax should look like defun but command and
> (compiled) code to be executed is put in a hashtable, so I don't
> need the interned symbols and I don't want to pollute the
> namespace. Until now I'm fine with using strings like in
>
>   (defcmd "name" (params) ...)
>
> and it's not overly important, but I noticed that I don't quite
> understand everything about names, symbols, strings and interning,
> so I'm just curious.

As I wrote, you have all these options:

name
:name
#:name
"NAME"

plus one more:
(defpackage "COMMAND-NAMES" (:nicknames "CN") (:use))

cn::name

One advantage of having interned symbols instead of strings, is that
you don't waste memory:

(progn
    (run-command 'name)
    (run-command 'name)
    (run-command 'name))

will allocate two symbols.

(progn
    (run-command "name")
    (run-command "name")
    (run-command "name"))

will allocate one symbol and three strings.  (An optimizing compiler
could in this specific case fold the three strings, but in general,
when the strings are in different compilation units or come from I/O,
you'll get duplicated data.)

Since a string needs about  1 word (length) and n characters,
while a symbols needs at most 5 words (name, package, value, function, plist),
(some implementations may have a lower overhead for symbols),
the cross over is at about 6 identical strings.


But the real problem is name colisions, which for symbols used for
their identity or their name occurs only when you import packages
after having interned the symbols in question.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Litter box not here.
You must have moved it again.
I'll poop in the sink. 
From: Stefan Nobis
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <87sltrv023.fsf@snobis.de>
Pascal Bourguignon <····@mouse-potato.com> writes:

> plus one more:
> (defpackage "COMMAND-NAMES" (:nicknames "CN") (:use))

Hmmm... the reader interns everything as soon as it reads the
words, so to put every symbol used as command names in this
package, one have to use in-package first, like this (to resemble
my project organisation a little bit):

(in-package :main-package)
(defpackage ...)

(in-package :cn)
(defmacro defcmd (name args &body body) ...)
(defcmd name1 () ...)
(defcmd name2 () ...)

This way the full qualified symbols are CN::NAME1, CN::NAME2. Is
this correct?

Is in the above scenario something like this possible:

(in-package :cn)
(defmacro defcmd (name args &body body)
  `((in-package :main-package)
   ... ,@body ...
   (in-package :cn)))

So every commands in body are executed in the context of
:main-package.

-- 
Stefan.
From: Pascal Bourguignon
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <87zmnzz27a.fsf@thalassa.informatimago.com>
Stefan Nobis <······@gmx.de> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> plus one more:
>> (defpackage "COMMAND-NAMES" (:nicknames "CN") (:use))
>
> Hmmm... the reader interns everything as soon as it reads the
> words, so to put every symbol used as command names in this
> package, one have to use in-package first, like this (to resemble
> my project organisation a little bit):

Why do you cut important information?
Well, I know, I do it too, but really, is it so hard to read ONE more line?

> (defpackage "COMMAND-NAMES" (:nicknames "CN") (:use))
> 
> cn::name


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?
From: Stefan Nobis
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <877jb3qhye.fsf@snobis.de>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Well, I know, I do it too, but really, is it so hard to read ONE
> more line?

No, not reading, but understanding.

>> (defpackage "COMMAND-NAMES" (:nicknames "CN") (:use))

>> cn::name

I tried this

,----
| CL-USER> (defpackage :command-names (:nicknames :cn) (:use))
| #<PACKAGE COMMAND-NAMES>
| CL-USER> (defvar *table* (make-hash-table :test 'equalp :size 10))
| *TABLE*
| CL-USER> (defmacro defcmd (name args &body body) `(setf (gethash ,name *table*) (lambda ,args ,@body)))
| DEFCMD
| CL-USER> (defcmd cn::my-cmd () (princ "I'm here"))
| EVAL: variable COMMAND-NAMES::MY-CMD has no value
|    [Condition of type SYSTEM::SIMPLE-UNBOUND-VARIABLE]
`----

and there's an error. Even if i try this

,----
| CL-USER> (in-package :cn)
| #<PACKAGE COMMAND-NAMES>
| CN> (cl-user::defcmd my-cmd () (princ "I'm here"))
`----

I get the same error.

*table* must not be in package :CN, defcmd may be in :CN and all
via defcmd defined commands should be in :CN. How do I do this? I
still don't understand it.

-- 
Stefan.
From: Harald Hanche-Olsen
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <pcosltrm7pk.fsf@shuttle.math.ntnu.no>
+ Stefan Nobis <······@gmx.de>:

| ,----
| | CL-USER> (defpackage :command-names (:nicknames :cn) (:use))
| | #<PACKAGE COMMAND-NAMES>
| | CL-USER> (defvar *table* (make-hash-table :test 'equalp :size 10))
| | *TABLE*
| | CL-USER> (defmacro defcmd (name args &body body) `(setf (gethash ,name *table*) (lambda ,args ,@body)))
| | DEFCMD
| | CL-USER> (defcmd cn::my-cmd () (princ "I'm here"))
| | EVAL: variable COMMAND-NAMES::MY-CMD has no value
| |    [Condition of type SYSTEM::SIMPLE-UNBOUND-VARIABLE]
| `----

MACROEXPAND-1 is your friend in situations like this.

(macroexpand-1 '(defcmd cn::my-cmd () (princ "I'm here")))

=> (setf (gethash command-names::my-cmd *table*)
     (lambda () (princ "I'm here")))

You need to slap a quote on that symbol in there.  Like so:

(defmacro defcmd (name args &body body) 
  `(setf (gethash ',name *table*) (lambda ,args ,@body)))

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Stefan Nobis
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <871x1aa3si.fsf@snobis.de>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> You need to slap a quote on that symbol in there.

Argh! I'm so blind. Thank you very much!

-- 
Stefan.
From: Kalle Olavi Niemitalo
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <87sltrpb6t.fsf@Astalo.kon.iki.fi>
Pascal Bourguignon <····@mouse-potato.com> writes:

> You can use UNINTERN, what if:
>
> (my-macro random-symbol-number-42) ; ok, new interned symbol, is uninterned.
> (my-macro defun) ; oops, you unintern a useful symbol!

Uninterning COMMON-LISP:DEFUN is not as harmful as one might assume.

* *package*

#<PACKAGE "COMMON-LISP-USER">
* (unintern 'defun)

NIL
* (defun foo ())

FOO
* 

DEFUN is accessible in the COMMON-LISP-USER package, because it is
an external symbol in COMMON-LISP, which COMMON-LISP-USER uses.
Because DEFUN has not been interned in COMMON-LISP-USER,
uninterning it from there has no effect.
From: Pascal Bourguignon
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <87sltrz1d6.fsf@thalassa.informatimago.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> You can use UNINTERN, what if:
>>
>> (my-macro random-symbol-number-42) ; ok, new interned symbol, is uninterned.
>> (my-macro defun) ; oops, you unintern a useful symbol!
>
> Uninterning COMMON-LISP:DEFUN is not as harmful as one might assume.
>
> * *package*
>
> #<PACKAGE "COMMON-LISP-USER">
> * (unintern 'defun)
>
> NIL
> * (defun foo ())
>
> FOO
> * 
>
> DEFUN is accessible in the COMMON-LISP-USER package, because it is
> an external symbol in COMMON-LISP, which COMMON-LISP-USER uses.
> Because DEFUN has not been interned in COMMON-LISP-USER,
> uninterning it from there has no effect.

Indeed, UNINTERN is not the indiscriminating bad guy I thought he
was. Sorry, UNINTERN.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: Barry Margolin
Subject: Re: Macros, Symbols and Strings
Date: 
Message-ID: <barmar-A0D920.22285428112005@comcast.dca.giganews.com>
In article <··············@Astalo.kon.iki.fi>,
 Kalle Olavi Niemitalo <···@iki.fi> wrote:

> Pascal Bourguignon <····@mouse-potato.com> writes:
> 
> > You can use UNINTERN, what if:
> >
> > (my-macro random-symbol-number-42) ; ok, new interned symbol, is uninterned.
> > (my-macro defun) ; oops, you unintern a useful symbol!
> 
> Uninterning COMMON-LISP:DEFUN is not as harmful as one might assume.
> 
> * *package*
> 
> #<PACKAGE "COMMON-LISP-USER">
> * (unintern 'defun)
> 
> NIL
> * (defun foo ())
> 
> FOO
> * 
> 
> DEFUN is accessible in the COMMON-LISP-USER package, because it is
> an external symbol in COMMON-LISP, which COMMON-LISP-USER uses.
> Because DEFUN has not been interned in COMMON-LISP-USER,
> uninterning it from there has no effect.

It would still be a bad idea for his macro to perform this UNINTERN.  
What if:

(defvar *foo* 3)
(my-macro *foo*); oops, you unintern a useful symbol

I don't think there's any way for the macro to determine if the symbol 
was interned as a result of reading his macro invocation.

Maclisp used to have an option to the Garbage Collector called GCTWA: GC 
Truly Worthless Atoms (symbols were often called atoms in Maclisp 
internals).  This caused it to collect symbols that were interned but 
not otherwise referenced.  There may be analogous 
implementation-dependent options in modern CL implementations.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***