help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Mentioning symbol put it to obarray?


From: Pascal J. Bourguignon
Subject: Re: Mentioning symbol put it to obarray?
Date: Mon, 21 Jan 2013 23:49:49 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux)

Oleksandr Gavenko <gavenkoa@gmail.com> writes:

> I execute code:
>
>   (put 'xxx 'some "value")
>
> and found symbol "xxx" in obarray. Also such code always invoke error:
>
>   (mapatoms (lambda (ob) (when (eq ob 'XYZ) (error "ok"))) obarray)
>
> for any "XYZ" because after parsing above line and before evaluation "XYZ"
> put to obarray...
>
> So mentioning any symbol make it globally available (existing)?
>
> Is it garbage collected from (remember about link in obarray)?

Symbols that are interned in an obarray are referenced by the obarray.
Therefore they cannot be garbage collected as long as the obarray cannot
be garbage collected.

And the obarray that is referenced by the variable obarray cannot be
garbage collected.

But other obarrays can be garbage collected, and as long as there are no
other references to the symbols it has interned, those symbols can be
garbage collected.

You can also create symbols that are not interned in any obarray, and
those symbols can be garbage collected just like any other lisp object.


One thing to note however: a symbol can be interned only in a single
obarray.  You cannot "put" a symbol in any way into two different
obarrays.


obarray is the variable that references the current obarray.  It is the
obarray that is used to intern the symbols that are read.  Therefore
when you "execute" some form such as:

   (put 'xxx 'some "value")

First, it must be _read_.  When reading such a sexp, the symbols are
interned in the current obarray (the one referenced by the variable
obarray).  So if the symbols named "xxx" and "some" didn't exist before,
then will be created and interned in the obarray now.

Once the form has been read, the lisp reader returns the lisp object it
has read.  In the above example, it is a cons cell.

    +-------------------------------------------------+
    | (put 'xxx 'some "value")                        |
    |                                                 |
    |  this one                                       |
    |   |                                             |
    |   v                                             |
    | +---+---+   +---+---+   +---+---+   +---+---+   |
    | | * | * |-->| * | * |-->| * | * |-->| * |nil|   |
    | +---+---+   +---+---+   +---+---+   +---+---+   |
    |   |           |           |           |         |
    |   v           |           |           v         |
    | +-----+       |           |         +---------+ |
    | | put |       |           |         | "value" | |
    | +-----+       |           |         +---------+ |
    |               |           v                     |
    |               |         +---+---+   +---+---+   |
    |               |         | * | * |-->| * |nil|   |
    |               |         +---+---+   +---+---+   |
    |               |           |           |         |
    |               |           v           v         |
    |               |         +-------+   +------+    |
    |               |         | quote |   | some |    |
    |               |         +-------+   +------+    |
    |               v                                 |
    |             +---+---+   +---+---+               |
    |             | * | * |-->| * |nil|               |
    |             +---+---+   +---+---+               |
    |               |           |                     |
    |               v           v                     |
    |             +-------+   +-----+                 |
    |             | quote |   | xxx |                 |
    |             +-------+   +-----+                 |
    +-------------------------------------------------+

This cons cell is then passed to the function eval, to be evaluated.


Similarly when evaluating the

   (mapatoms (lambda (ob) (when (eq ob 'XYZ) (error "ok"))) obarray)

form, the reader must first intern all those symbols.  Therefore it will
always signal the error.



You can prevent the lisp reader to intern the symbol it reads, by prefix
them with "#:":

   '#:uninterned-symbol
   --> #:uninterned-symbol

   (mapatoms (lambda (ob) (when (eq ob '#:XYZ) (error "ok"))) obarray)
   --> nil ; no error signaled.

You can also unintern a symbol at run-time:

  (let ((sym 'XYZ))
    (unintern sym)
    (mapatoms (lambda (ob) (when (eq ob sym) (error "ok"))) obarray))
  --> nil

Here, the symbol named "XYZ" is interned when the let form is read.  But
when it's evaluated, it gets uninterned from the obarray.  Therefore
when mapatoms is evaluated it doesn't find the symbol referenced by sym
(ie. XYZ) inside the obarray.  If you return it, it will be printed as
an uninterned symbol:

 (let ((sym 'XYZ))
    (unintern sym)
    (mapatoms (lambda (ob) (when (eq ob sym) (error "ok"))) obarray)
    sym)
  --> #:XYZ

If you don't keep references to uninterned symbols, they can be garbage
collected.


Often, symbols have references to functions or other lisp objects (in
their function slot or their value slot, or also in their plist slot),
so you wouldn't want in general to unintern symbol indiscriminately.
You could break your lisp image doing so (you could remove an important
function that is used by emacs).


If you've been attentive, you may have noticed that the current obarray
is referenced by the variable obarray, and that this variable is named
by a symbol named "obarray" that is interned, in the current obarray.
There's a circle here, and that should not prevent the garbage collector
to collect them both right?  Well happily, the variable obarray is
defined in C code, (it's Vobarray in C), and the symbol naming it could
be uninterned, the C variable would still exist (you just couldn't
access it anymore from lisp) and therefore the obarray is safely
referenced by the C variable Vobarray, and the symbols it contains are
safe from the garbage collector.  (The C variables are in the root set
for the garbage collector).

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]