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.

4
  • I know what lexical-binding and dynamic-binding are, but when encountering “buffer-local”, I get confused.
    – shynur
    Mar 21 at 16:38
  • Somewhat a duplicate of emacs.stackexchange.com/questions/27581 except for the focus on buffer-local-ness.
    – phils
    Mar 21 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 at 1: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 at 9:10

1 Answer 1

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.

1
  • 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 bindings just like let and setq, even though its argument is symbol-type.
    – shynur
    Mar 22 at 9:17

Your Answer

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

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