2

I am reading the GNU Emacs Lisp Reference Manual, 9.3 Creating and Interning Symbols:

Each element of the obarray is a bucket which holds all the symbols with a given hash code; to look for a given name, it is sufficient to look through all the symbols in the bucket for that name’s hash code.

The Manual says that an element is a bucket and can hold more than one symbol.

But in my trial:

ELISP> (let (Is-there-a-bucket?)
         (mapc #'(lambda (element)
                   (unless (or
                            (eq element 0)
                            (symbolp element))
                     (setq Is-there-a-bucket? t)))
               obarray)
         Is-there-a-bucket?)
nil

I found that each element of the obarray is either a fixnum 0 or a symbol (as mentioned later in the Manual), instead of the so-called bucket.

This is where I get confused.

2 Answers 2

2

You should just read the source. Each bucket is a linked list of symbols, but it is an intrusive list. That means that the next pointer for the list is part of the objects in the list, rather than being part of an external data structure. If you look in lisp.h, you will find that each Lisp_Symbol has a struct Lisp_Symbol *next member. There is a comment that says /* Next symbol in obarray bucket, if the symbol is interned. */. So each time you saw a symbol, that was the start of some bucket. I don’t think that there is any way to access the next pointer from Lisp code.

If you want to enumerate all interned symbols, use the mapatoms function. It is written in C, and correctly walks the linked lists of symbols.

Intrusive lists are super common in C, and unheard of in Lisp. C simply doesn’t have a nice generic linked list, and even if it did the fact that it needs to introduce an extra level of indirection means that using it would be less efficient than the intrusive list. So C programmers just write intrusive lists even though from the Lisp point of view it is wasteful and burdensome.

0
3

Yes, the element (the interned symbol) passes symbolp, but it also contains a next pointer that the C code can use to access the next element with the same hash code. This is where the “bucket” comes from. You can also think of it as a singly-linked list, if that’s easier for you.

It’s important to note that this next pointer is invisible to Lisp, so the only way to iterate over an obarray is via mapatoms.

All of this is mentioned in the documentation you linked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.