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

shynur
  • 4,065
  • 1
  • 3
  • 23
  • 1
    Note that in upstream Emacs, this has changed: `(let ((test 233)) (lambda ())) ;; ==> (closure (t) nil)` – NickD Apr 13 '23 at 14:33

1 Answers1

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.

NickD
  • 27,023
  • 3
  • 23
  • 42
  • 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](https://git.savannah.gnu.org/cgit/emacs.git/tree/doc/lispref/variables.texi#n1186): “*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 Apr 13 '23 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 Apr 13 '23 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 Apr 13 '23 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 Apr 13 '23 at 13:49
  • FYI the code documents that "A value of `(t)` indicates an empty environment" and "Every element of this list can be either a cons (VAR . VAL) specifying a lexical binding, or a single symbol VAR indicating that this variable should use dynamic scoping." – phils Apr 13 '23 at 13:51
  • And in 28.2 that example closure includes a `t`. *It doesn't matter* because it's an implementation detail which is subject to change (and clearly did). I would guess that the `t` isn't strictly needed if a non-empty lexical environment is present, but in the past values were probably pushed onto that list, and more recently it omits the `t` if it doesn't need to be there. – phils Apr 13 '23 at 13:53
  • 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 Apr 13 '23 at 13:58
  • The "single symbol VAR" sentence was added to the parenthetical section that @shynur complained about on April 18 and the `t` part was excised (see commit [60560cc7adfe685ef8c04623a6d019dc659123b1](https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=60560cc7adfe685ef8c04623a6d019dc659123b1) and bug#62840). In that bug, 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. – NickD Apr 24 '23 at 18:32
  • @NickD: Your last comment contained useful information. Consider incorporating it into your answer? – shynur Apr 29 '23 at 19:18
  • Will do - but not tonight... – NickD Apr 30 '23 at 00:00
  • @shynur: updated the answer. – NickD May 10 '23 at 17:45