3
(let ((test 233))
  (lambda ()))
;; ==> (closure ((test . 233) t)
;; ==>   nil)

I am wondering why not simply choose a proper alist, e.g.:

((test . 233)) ; instead of ((test . 233) t)

As far as I know, the latter conses more bytes.


emacs-version: 28.2
system-configuration: x86_64-w64-mingw32

1
  • 1
    Note that in upstream Emacs, this has changed: (let ((test 233)) (lambda ())) ;; ==> (closure (t) nil)
    – NickD
    Commented Apr 13, 2023 at 14:33

1 Answer 1

2

Try with a function that takes an argument and has a body:

(let ((foo 233)) (lambda (x) (* x foo)))
;; ==> (closure ((foo . 233)) (x) (* x foo))

The Closures section of the Elisp Reference manual says:

   Currently, an Emacs Lisp closure object is represented by a list with
the symbol ‘closure’ as the first element, a list representing the
lexical environment as the second element, and the argument list and
body forms as the remaining elements:

     ;; lexical binding is enabled.
     (lambda (x) (* x x))
          ⇒ (closure (t) (x) (* x x))

However, the fact that the internal structure of a closure is exposed to
the rest of the Lisp world is considered an internal implementation
detail.  For this reason, we recommend against directly examining or
altering the structure of closure objects.

Why the t is added in this case is an implementation detail (which is subject to change).


EDIT: Documenting the t seemed unnecessary in the light of the above. Indeed, the "single symbol VAR" sentence that @phils points out in a comment below, was added to the parenthetical section that @shynur complained about above and the t part was excised (see commit 60560cc7adfe685ef8c04623a6d019dc659123b1 and bug#62840), where Stefan Monnier mentions that it is still possible apparently for a t to be added, but it is an implementation detail and not important to document. But it is not clear to me at least when and where that t might be added.

11
  • 1
    Yes, it is an internal detail as the manual says. But it is also a behavior that is clearly stated in 12.10.3: “the lexical environment is an alist of symbol-value pairs, with the final element in the alist being the symbol t rather than a cons cell.” Is this a documentation bug? (Of course, I know this is not something the average users need to know. But as an Elisp learner, this inconsistency between documentation and actual behavior made me impossible to continue learning confidently.)
    – shynur
    Commented Apr 13, 2023 at 13:28
  • It's not something that any user needs to know, unless they are planning to modify the C code implementation of lexical binding in Emacs. It's an internal implementation detail which happens to be visible, and therefore is described in the manual. You can very safely ignore it.
    – phils
    Commented Apr 13, 2023 at 13:42
  • That said, what is this inconsistency between documentation and action behaviour that you are seeing? It seems to be exactly as described.
    – phils
    Commented Apr 13, 2023 at 13:44
  • @phils: “what is this inconsistency between documentation and action behaviour that you are seeing?” --- See NickD's example where the closure doesn't contain a t. (I tested it in v30.0)
    – shynur
    Commented Apr 13, 2023 at 13:49
  • 2
    Emacs documentation is very good in general, but you're really going to struggle if you let something as inconsequential as this make it "impossible to continue learning confidently" because despite the overall quality, documentation bugs are far from unusual. If you find one, you can M-x report-emacs-bug to have it fixed.
    – phils
    Commented Apr 13, 2023 at 13:58

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.