how to check dynamically if lexical scoping is active in Emacs Lisp

The variable lexical-binding specifies whether to use lexical scoping when evaluating code in the current buffer or el file. But checking the value of this variable at a point of code is not a reliable way to check if lexical scoping applies at that point. Instead use the following s-expression which I got from here.

(let ((x nil)
      (f (let ((x t)) (lambda () x))))
  (funcall f))

The expression evaluates to t in lexical scoping, to nil in dynamic scoping, provided that nobody has declared x as a special variable elsewhere. Let’s make it a macro.

(defmacro my-lexical-binding-q ()
  '(let ((x nil)
         (f (let ((x t)) (lambda () x))))
     (funcall f)))

Now wherever you put (print (my-lexical-binding-q)) in your code, it will tell you whether that part of your code is lexically scoped or not.

Just in case somebody declares x a special variable, let’s replace x with an uninterned symbol.

(defmacro my-lexical-binding-q ()
  (let ((tempvar (make-symbol "x")))
    `(let ((,tempvar nil)
           (f (let ((,tempvar t)) (lambda () ,tempvar))))
       (funcall f))))

When you run the following code in a dynamically scoped el file, it returns (nil t).

(eval
 '(progn
    (list lexical-binding
          (my-lexical-binding-q)))
 t)

The second argument of eval is t, so the progn form should be evaluated with lexical scoping, but the value of lexical-binding is still nil.

Another case when lexical-binding and (my-lexical-binding-q) return different values is when you run the following code in a dynamically scoped Emacs Lisp mode buffer.

(progn
  (print lexical-binding)
  (setq lexical-binding t)
  (print lexical-binding)
  (print (my-lexical-binding-q)))

That prints nil t nil. The variable lexical-binding is set to t, but you see that its effect is not immediate. When you evaluate (my-lexical-binding-q) again, it will return t. I’d advise you not to setq lexical-binding like that in your code. I’d set lexical-binding only as file variables. Don’t do (let ((lexical-binding t)) ...) either. Instead, use the function eval with second argument set to t.

Save the following to the file ~/lex0.el.

;; -*- lexical-binding:t -*-
(print
 (list lexical-binding
       (my-lexical-binding-q)))

Run the following code in a dynamically scoped el file.

(progn
  (print
   (list lexical-binding
         (my-lexical-binding-q)))
  
  (load "~/lex0.el")
  
  (print
   (list lexical-binding
         (my-lexical-binding-q))))

That will print (nil nil) (t t) (nil nil). That demonstrates how the variable lexical-binding works.

There is yet another case when lexical-binding and (my-lexical-binding-q) are different. Suppose you have a function defined in a lexically scoped el file, but you call that function from a dynamically scoped el file. If the function prints (list lexical-binding (my-lexical-binding-q)), what is printed? (nil t) is printed. Not a bug. It has to print (nil t).

This entry was posted in Emacs and tagged , , . Bookmark the permalink.

One Response to how to check dynamically if lexical scoping is active in Emacs Lisp

  1. Pingback: lexical scoping and dynamic scoping in Emacs Lisp | Yoo Box

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s