emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: lexical-binding defined by the caller not the called?


From: Pascal J. Bourguignon
Subject: Re: lexical-binding defined by the caller not the called?
Date: Sun, 28 Apr 2013 21:40:57 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux)

Nic Ferrier <address@hidden> writes:

> "Pascal J. Bourguignon" <address@hidden> writes:
>
>> Nic Ferrier <address@hidden> writes:
>
>>> How do I check for lexical-binding then?
>>
>> Read again the code I posted along.
>
> I did. I can't see how that shows me how to test lexical-binding though.

You keep saying things that are rather meaningless.

To test the value of the variable named lexical-binding, you just write
lexical-binding in a place in the code where it's evaluated.
For example: 

    (insert (if lexical-binding "lexical" "dynamic"))


To test whether a variable is a lexical variable or a special variable
you can use this macro:

(defmacro lexical-variable-p (symbol)
  `(let ((,symbol t))
     (flet ((f () ,symbol))
       (let ((,symbol nil))
         (f)))))

(eval-when (compile load eval) (setf lexical-binding t))
(let ((toto 42))
  (list (lexical-variable-p toto)
        (lexical-variable-p lexical-binding)))
;; --> (t nil)

(eval-when (compile load eval) (setf lexical-binding nil))
(let ((toto 42))
  (list (lexical-variable-p toto)
        (lexical-variable-p lexical-binding)))
;; --> (nil nil)



Notice that the result is independenant of the setting of
lexical-binding at run-time:

(eval-when (compile load eval) (setf lexical-binding t))
(let ((toto 42))
  (list (lexical-variable-p toto)
        (lexical-variable-p lexical-binding)
        (let ((lexical-binding nil))
          (list  (lexical-variable-p toto)
                 (lexical-variable-p lexical-binding)))))
;; --> (t nil (t nil))

(eval-when (compile load eval) (setf lexical-binding nil))
(let ((toto 42))
  (list (lexical-variable-p toto)
        (lexical-variable-p lexical-binding)
        (let ((lexical-binding t))
          (list  (lexical-variable-p toto)
                 (lexical-variable-p lexical-binding)))))
;; --> (nil nil (nil nil))




> It seems like I can't tell if I'm executing in a lexical-binding
> environment or not. 


The dynamic variable named lexical-binding tells you whether the
_current_, at the _time_ of execution, "environment" is lexical or not.

Of course, this is entirely irrelevant, since at run-time you don't
usually load or compile code.  But if you do, then lexical-binding tells
you whether let will establish lexical variables for new bindings.


> I want to be able to write a macro that understands when it is, or is
> not, executing code inside a lexical-binding environment.

Macros are expanded at compilation time, so again, it's totally
unrelated to whatever happens to lexical-binding at run-time.

You can just test lexical-binding in the macro:


(defmacro m (var init-expr incr-expr)
  (if lexical-binding
    `(let ((,var ,init-expr))
      (lambda () ,incr-expr ,var))
    (let ((unique-var (gensym)))
       `(progn
          (setf (symbol-value ',unique-var)  ,init-expr)
          (lambda () (let ((,var (symbol-value ',unique-var))) 
                        ,incr-expr
                        (setf (symbol-value ',unique-var) ,var)))))))

(eval-when (compile load eval) (setf lexical-binding nil))
(let ((f (m x 0 (incf x))))
  (list (macroexpand '(m x 0 (incf x)))
        (list (funcall f) (let ((x 42)) (funcall f))  (funcall f))))
;; --> ((progn (setf (symbol-value (quote #1=#:G123027)) 0)
;;         (lambda nil (let ((x (symbol-value (quote #1#)))) (incf x) (setf 
(symbol-value (quote #1#)) x))))
;;      (1 2 3))

(eval-when (compile load eval) (setf lexical-binding t))
(let ((f (m x 0 (incf x))))
  (list (macroexpand '(m x 0 (incf x)))
        (list (funcall f) (let ((x 42)) (funcall f))  (funcall f))))
;; --> ((let ((x 0)) (lambda nil (incf x) x))
;;      (1 2 3))




-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]