2

Two examples (both are in the *scratch* buffer and under lexical scoping rule):

  1. _

    (setq xx :default)
    
    (let ((xx :let))
      (with-current-buffer (get-buffer-create "tmp")
        (make-local-variable 'xx)
        ;; set the value of xx, buffer-locally
        (setq xx :tmp)) ; exit from "tmp"
      xx) ; ==> :tmp
    ;; I think that: after exiting from "tmp",
    ;; xx would restore its previous value
    ;; bound by `let`.
    ;; But in fact, it didn't evaluate to :let.
    
    (with-current-buffer "tmp"
      xx) ; ==> :default
    ;; It seems that even though `let`-binding was
    ;; created in "*scratch*", it removed the 
    ;; binding of the buffer-local variable
    ;; in the buffer "tmp" so that this form didn't
    ;; evaluate to :tmp.
    
  2. _

    (defvar yy :default)
    
    (let ((yy :let))
      (with-current-buffer (get-buffer-create "tmp")
        (make-local-variable 'yy)
        (setq yy :tmp))
      yy) ; ==> :let
    ;; yy restored its value created by `let`-bing
    ;; after switching back to the original buffer.
    ;; This is intuitive.
    
    (with-current-buffer "tmp"
      yy) ; ==> :tmp
    ;; `let`-binding didn't remove the binding created
    ;; by (setq yy :tmp).
    ;; It behaved differently from the previous example.
    

These comments show my two kinds of understanding, neither is self-consistent. And they are contradictory to each other.

Why are the results different for these two examples?
example-1: :tmp :default
example-2: :let :tmp

Is there any section, in the manual, explaining the above behaviors?
I did not find it.

shynur
  • 4,065
  • 1
  • 3
  • 23
  • I know what lexical-binding and dynamic-binding are, but when encountering “buffer-local”, I get confused. – shynur Mar 21 '23 at 16:38
  • Somewhat a duplicate of https://emacs.stackexchange.com/questions/27581 except for the focus on buffer-local-ness. – phils Mar 21 '23 at 21:37
  • 1
    It's probably worth keeping in mind that GNU Emacs has only supported lexical binding since version 24, released a little over a decade ago, and that there's 25+ years of only-dynamic-binding preceding that; so if you feel the documentation could be doing a better job of covering certain aspects which differ between the two, it's extremely possible that the documentation in question was mostly written before lexical binding was a thing. Documentation improvements can be suggested via `M-x report-emacs-bug`. – phils Mar 22 '23 at 01:14
  • @phils: This question had been bothering me for several days. One of my classmates is also reading this *manual*, and if he gets confused when encountering this question as well, it will be time for me to report a request for Documentation Improvement. – shynur Mar 22 '23 at 09:10

1 Answers1

2

Variables with dynamic scope can have global and buffer-local values, which are associated with the canonical symbol for the variable.

The global vs buffer-local concepts are irrelevant to lexically-scoped variables, which have "indefinite extent" within the lexical scope of the code in question, and (crucially) are not tied to the symbol of the same name.

As (make-local-variable 'xx) acts on the symbol xx, it has no bearing on any lexical variable xx in that code. (The same comment applies to any function which accesses a variable via a symbol argument.)

It will still cause a dynamically-scoped variable of that name to be buffer-local to the temp buffer, but the (setq xx :tmp) is setting the lexical variable. If you were to (set 'xx :tmp) OTOH, you'd be setting the dynamic buffer-local variable via the symbol.

C-hig (elisp)Lexical Binding is the node to read.

phils
  • 48,657
  • 3
  • 76
  • 115
  • ***Thanks a lot!*** My original thought was that: Since `make-local-variable` is a *built-in* function, I thought it would be able to access *lexical binding*s just like `let` and `setq`, even though its argument is *symbol*-type. – shynur Mar 22 '23 at 09:17