From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: pjb@informatimago.com (Pascal J. Bourguignon) Newsgroups: gmane.emacs.help Subject: Re: lexical-let detail semantics Date: Mon, 27 Jul 2009 15:16:44 +0200 Organization: Anevia SAS Message-ID: <7c63deuuyr.fsf@pbourguignon.anevia.com> References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1248702823 28295 80.91.229.12 (27 Jul 2009 13:53:43 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 27 Jul 2009 13:53:43 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Mon Jul 27 15:53:36 2009 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1MVQdy-0003hH-Dw for geh-help-gnu-emacs@m.gmane.org; Mon, 27 Jul 2009 15:53:34 +0200 Original-Received: from localhost ([127.0.0.1]:56408 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MVQdx-0003KZ-Kx for geh-help-gnu-emacs@m.gmane.org; Mon, 27 Jul 2009 09:53:33 -0400 Original-Path: news.stanford.edu!headwall.stanford.edu!news.glorb.com!news2.glorb.com!proxad.net!feeder1-2.proxad.net!cleanfeed1-b.proxad.net!nnrp10-1.free.fr!not-for-mail Original-Newsgroups: gnu.emacs.help Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en X-Disabled: X-No-Archive: no User-Agent: Gnus/5.101 (Gnus v5.10.10) Emacs/22.2 (gnu/linux) Cancel-Lock: sha1:MTMyNTUzMmUwMDUzMzgzMzJjMmYwZWQ1Mzk5NDdlZmE5Mjk2NzA3NA== Original-Lines: 173 Original-NNTP-Posting-Date: 27 Jul 2009 15:16:45 MEST Original-NNTP-Posting-Host: 88.170.236.224 Original-X-Trace: 1248700605 news-3.free.fr 10240 88.170.236.224:34505 Original-X-Complaints-To: abuse@proxad.net Original-Xref: news.stanford.edu gnu.emacs.help:171246 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:66432 Archived-At: Daniel Kraft writes: > Hi, > > I'm working on an implementation of elisp for GNU Guile, and want to > include the lexical-let construct from the Common Lisp Extensions of > elisp. There are some details of its semantics I'm not sure about and > that are not clarified in the documentation of lexical-let, so I had > to do some experiments. Here are two questions that came up during > these where I'd love to hear comments from regular elisp users: > > > 1) let within lexical-let: > > (setq a 1) > (defun dyna () a) > (lexical-let ((a 2)) > (let ((a 3)) > (print (dyna)))) > => 1 If you have a look at the macro expansion of lexical-let, it looks like it is the intended behavior. (macroexpand '(lexical-let ((a 2)) (let ((a 3)) (print (dyna))))) --> (let ((--cl-a-- 2)) (letf (((symbol-value (quote --cl-a--)) 3)) (print (dyna)))) > My first thought was that a let within the lexical scope of another > lexical-let would revert the symbols to dynamic scoping again, but it > seems that let behaves just as if it was lexical-let for symbols > already lexically bound. > > Is this 'expected behaviour' or something 'by chance'? Do you think > it is necessary for compatibility with (most) existing code to mimic > this behaviour or would it be ok for the code above to print 3? I agree, it's not what I'd expect either. Have a look at the Common Lisp reference: http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm http://www.lispworks.com/documentation/HyperSpec/Body/d_specia.htm I would translate the above forms in Common Lisp as: (SETF (SYMBOL-VALUE 'A) 1) (DEFUN DYNA () (DECLARE (SPECIAL A)) A) (LET ((A 2)) (LET ((A 3)) (DECLARE (SPECIAL A)) (PRINT (DYNA)))) prints: 3 --> 3 You can avoid the problem by putting the dynaminc bindings outside of reach of lexical-let: (defun call-dyna () (let ((a 3)) (print (dyna)))) (lexical-let ((a 2)) (call-dyna)) prints: 3 --> 3 Notice also that in languages that have both special variables and lexical variables, it is found worthwhile to keep them in separate name spaces. In ISO-LISP, this is done with the (dynamic var) form for special variables. In Common Lisp it's done with the *earmuff* convention. (defvar *a* 1) (defun dyna () (print *a*)) (lexical-let ((a 2)) (let ((*a* 3)) (dyna))) prints: 3 --> 3 which is what we expect: (macroexpand '(lexical-let ((a 2)) (let ((*a* 3)) (dyna)))) --> (let ((--cl-a-- 2)) (let ((*a* 3)) (dyna))) You may report the bug to the maintainers, but I'm not sure it's worthwhile. If you want a real language, perhaps you could use emacs-cl? http://www.lisp.se/emacs-cl/ > In contrast, the code: > > (setq a 1) > (defun dyna () a) > (lexical-let ((a 2)) > ((lambda (a) > (print (dyna))) 3)) > => 3 > > does indeed revert a to dynamic binding... This seems somewhat > inconsistent to me (although of course argument-lists and let's are > not really the same thing). Yes, there's a (theorical) equivalence between lambda and let. In this case again the macroexpansion explains why it works: (macroexpand '(lexical-let ((a 2)) ((lambda (a) (print (dyna))) 3))) --> (let ((--cl-a-- 2)) (funcall (function (lambda (a) (print (dyna)))) 3)) > 2) Closures: > > I'm happy that lexical-let works well to build closures (and in fact > it seems that this is the main intention for lexical-let at all); > however this code does not work as expected: > > (setq a 1) > (lexical-let ((a 2)) > ((lambda () (print a)))) > => 1 > > I don't know why, but it seems that calling a closure directly fails, > while storing it and calling it later succeeds (as in the examples at > http://www.delorie.com/gnu/docs/emacs/cl_21.html for instance). Is > this a bug or again something expected? If the latter, what's the > exact rationale and semantics then? I guess you have a bug in your version. Mine works ok. Again, the macroexpansion explains what lexical-let does in this case: (macroexpand '(lexical-let ((a 2)) ((lambda () (print a))))) --> (let ((--cl-a-- (make-symbol "--a--"))) (setf (symbol-value --cl-a--) 2) (funcall (list (quote lambda) (quote (&rest --cl-rest--)) (list (quote apply) (function (lambda (G93796) (print (symbol-value G93796)))) (list (quote quote) --cl-a--) (quote --cl-rest--))))) In emacs-version "22.2.1", I get the right result: (lexical-let ((a 2)) ((lambda () (print a)))) prints: 2 --> 2 -- __Pascal Bourguignon__