* lexical-binding defined by the caller not the called? @ 2013-04-28 11:26 Nic Ferrier 2013-04-28 11:53 ` Pascal J. Bourguignon 0 siblings, 1 reply; 7+ messages in thread From: Nic Ferrier @ 2013-04-28 11:26 UTC (permalink / raw) To: emacs-devel Imagine this is a file: ;;; -*- lexical-binding: t -*- (defun my-cool-fun () lexical-binding) (ert-deftest my-cool-fun () (should (my-cool-fun))) (ert 'my-cool-fun) ;;; End eval-buffer that and it fails. Why does it fail? it appears that lexical-binding is defined by the caller of a function, not the called function (and the file defining ert is not lexical-binding: t). I thought it was the other way around. Am I seeing some bug or is this the correct behaviour? Nic Ferrier ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: lexical-binding defined by the caller not the called? 2013-04-28 11:26 lexical-binding defined by the caller not the called? Nic Ferrier @ 2013-04-28 11:53 ` Pascal J. Bourguignon 2013-04-28 13:59 ` Nic Ferrier 0 siblings, 1 reply; 7+ messages in thread From: Pascal J. Bourguignon @ 2013-04-28 11:53 UTC (permalink / raw) To: emacs-devel Nic Ferrier <nferrier@ferrier.me.uk> writes: > Imagine this is a file: > > ;;; -*- lexical-binding: t -*- > > (defun my-cool-fun () > lexical-binding) > > (ert-deftest my-cool-fun () > (should (my-cool-fun))) > > (ert 'my-cool-fun) > > ;;; End > > > eval-buffer that and it fails. Why does it fail? it appears that > lexical-binding is defined by the caller of a function, not the called > function (and the file defining ert is not lexical-binding: t). > > I thought it was the other way around. > > Am I seeing some bug or is this the correct behaviour? It fails because lexical-binding is a special variable (in CL terms). ---(cool.el)------------------------------------------------------------ ;;; -*- lexical-binding: t -*- (let ((lexical-variable 42)) (defun my-cool-fun () lexical-variable)) ; this lexical-variable is a lexical variable ;;; End ------------------------------------------------------------------------ ---(cool-test.el)------------------------------------------------------- ;;; -*- lexical-binding: nil -*- (ert-deftest my-cool-fun () (should (let ((lexical-variable 'not!)) ; this lexical-variable is not (eql 42 (my-cool-fun))))) ; a lexical variable! (ert 'my-cool-fun) ;;; End ------------------------------------------------------------------------ Selector: my-cool-fun Passed: 1 Failed: 0 Total: 1/1 Started at: 2013-04-28 13:51:49+0200 Finished. Finished at: 2013-04-28 13:51:49+0200 -- __Pascal Bourguignon__ http://www.informatimago.com/ A bad day in () is better than a good day in {}. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: lexical-binding defined by the caller not the called? 2013-04-28 11:53 ` Pascal J. Bourguignon @ 2013-04-28 13:59 ` Nic Ferrier 2013-04-28 14:10 ` Pascal J. Bourguignon 0 siblings, 1 reply; 7+ messages in thread From: Nic Ferrier @ 2013-04-28 13:59 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: emacs-devel "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > It fails because lexical-binding is a special variable (in CL terms). Doh. That is a really good point. How do I check for lexical-binding then? Nic ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: lexical-binding defined by the caller not the called? 2013-04-28 13:59 ` Nic Ferrier @ 2013-04-28 14:10 ` Pascal J. Bourguignon 2013-04-28 17:50 ` Nic Ferrier 0 siblings, 1 reply; 7+ messages in thread From: Pascal J. Bourguignon @ 2013-04-28 14:10 UTC (permalink / raw) To: emacs-devel Nic Ferrier <nferrier@ferrier.me.uk> writes: > "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > >> It fails because lexical-binding is a special variable (in CL terms). > > Doh. > > That is a really good point. > > How do I check for lexical-binding then? Read again the code I posted along. -- __Pascal Bourguignon__ http://www.informatimago.com/ A bad day in () is better than a good day in {}. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: lexical-binding defined by the caller not the called? 2013-04-28 14:10 ` Pascal J. Bourguignon @ 2013-04-28 17:50 ` Nic Ferrier 2013-04-28 19:40 ` Pascal J. Bourguignon 2013-05-04 20:01 ` Stefan Monnier 0 siblings, 2 replies; 7+ messages in thread From: Nic Ferrier @ 2013-04-28 17:50 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: emacs-devel "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > Nic Ferrier <nferrier@ferrier.me.uk> 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. It seems like I can't tell if I'm executing in a lexical-binding environment or not. I want to be able to write a macro that understands when it is, or is not, executing code inside a lexical-binding environment. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: lexical-binding defined by the caller not the called? 2013-04-28 17:50 ` Nic Ferrier @ 2013-04-28 19:40 ` Pascal J. Bourguignon 2013-05-04 20:01 ` Stefan Monnier 1 sibling, 0 replies; 7+ messages in thread From: Pascal J. Bourguignon @ 2013-04-28 19:40 UTC (permalink / raw) To: emacs-devel Nic Ferrier <nferrier@ferrier.me.uk> writes: > "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > >> Nic Ferrier <nferrier@ferrier.me.uk> 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 {}. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: lexical-binding defined by the caller not the called? 2013-04-28 17:50 ` Nic Ferrier 2013-04-28 19:40 ` Pascal J. Bourguignon @ 2013-05-04 20:01 ` Stefan Monnier 1 sibling, 0 replies; 7+ messages in thread From: Stefan Monnier @ 2013-05-04 20:01 UTC (permalink / raw) To: Nic Ferrier; +Cc: Pascal J. Bourguignon, emacs-devel >>> 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. > It seems like I can't tell if I'm executing in a lexical-binding > environment or not. > I want to be able to write a macro that understands when it is, or is > not, executing code inside a lexical-binding environment. It's a good question. But you need to be careful about what you mean because the code you showed does not do what you describe (e.g. it doesn't do any macro expansion). Testing the value of `lexical-binding' from within a function won't tell you if that function is itself using lexical binding or not. But testing `lexical-binding' during macro expansion should tell you whether the expanded code will be interpreted as lexically scoped or not. It's actually not 100% reliable (e.g. lexical-binding is a buffer-local variable, so if you switch buffer during your macro expansion, you might bump into some corner cases), but it should work well in practice (tho less so in 24.1 where there were a few more problematic cases that I had forgotten). Stefan ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-05-04 20:01 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-04-28 11:26 lexical-binding defined by the caller not the called? Nic Ferrier 2013-04-28 11:53 ` Pascal J. Bourguignon 2013-04-28 13:59 ` Nic Ferrier 2013-04-28 14:10 ` Pascal J. Bourguignon 2013-04-28 17:50 ` Nic Ferrier 2013-04-28 19:40 ` Pascal J. Bourguignon 2013-05-04 20:01 ` Stefan Monnier
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.