[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 {}.