From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Kent M Pitman Newsgroups: gmane.emacs.help Subject: Re: Differences between Elisp and Lisp Date: 29 Apr 2003 11:43:12 -0400 Organization: My ISP can pay me if they want an ad here. Sender: help-gnu-emacs-bounces+gnu-help-gnu-emacs=m.gmane.org@gnu.org Message-ID: References: <3eae89b4$0$13158$3b214f66@usenet.univie.ac.at> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1051631316 23791 80.91.224.249 (29 Apr 2003 15:48:36 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Tue, 29 Apr 2003 15:48:36 +0000 (UTC) Original-X-From: help-gnu-emacs-bounces+gnu-help-gnu-emacs=m.gmane.org@gnu.org Tue Apr 29 17:48:35 2003 Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 19AXLO-0006BP-00 for ; Tue, 29 Apr 2003 17:48:34 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 19AXId-0004iu-05 for gnu-help-gnu-emacs@m.gmane.org; Tue, 29 Apr 2003 11:45:43 -0400 Original-Path: shelby.stanford.edu!newsfeed.stanford.edu!logbridge.uoregon.edu!feed2.news.rcn.net!rcn!priapus.visi.com!news-out.visi.com!petbe.visi.com!uunet!ash.uu.net!nntp.TheWorld.com!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 87 Original-NNTP-Posting-Host: shell01.theworld.com Original-X-Trace: pcls4.std.com 1051630992 21336 199.172.62.241 (29 Apr 2003 15:43:12 GMT) Original-X-Complaints-To: abuse@TheWorld.com Original-NNTP-Posting-Date: Tue, 29 Apr 2003 15:43:12 +0000 (UTC) User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 Original-Xref: shelby.stanford.edu gnu.emacs.help:112518 Original-To: help-gnu-emacs@gnu.org X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: help-gnu-emacs-bounces+gnu-help-gnu-emacs=m.gmane.org@gnu.org Xref: main.gmane.org gmane.emacs.help:9016 X-Report-Spam: http://spam.gmane.org/gmane.emacs.help:9016 Thomas Link writes: > > I thought that CL already implemented lexical binding? At least within > > a let form (or "lexical-let"). > > I guess it's faking lexical binding by replacing variable names with > gensyms. This makes it pseudo-lexical but not more efficient. In addition to having questionable efficiency issues, such a strategy also eliminates the one primary reason that more than anything justifies lexical scoping--the ability to know 'just by looking' that no other uses of the variable exist and that it's ok to optimize. Consider: (let ((x 1)) (f x)) which might result from a macro expansion. You'd like this to compile the same as (f 1). But if you just turn it into (let ((x0001 1)) (f x0001)) the compiler still has to worry that x0001 might be accessible within the definition of f, and so it can't make the binding for it go away. What allows you to make the binding go away is not the _fact_ that this is the only use of x0001 but the _lexically apparent knowledge_ that this is the only use of x0001. And that knowledge comes from 'real lexicality', not from clever tricks. [Even if you have access to the source code of 'f', you can't rely on that since f might be later redefined. It should be possible to later introduce a new f with different properties without recompiling callers to f.] Additionally, tricks like the above mean that in error breaks, the stack is cluttered with myriad special variable bindings that one really doesn't want to have to paw through. > > If emacs just went to using lexical binding in the large, I suspect > > that it would cause lots of problems with existing packages. I have > > used dynamic scoping to achieve ends in the past, which might be a bit > > nasty, but it does work! > > Correct me if I'm wrong, but e.g. Common Lisp has dynamic binding for > variables defined with defvar. The following works with clisp: > > (defvar x 1) > (defun y (a) (+ x 1)) > (y 1) => 2 > (let ((x 10)) (y 1)) => 11 > > So one could have both. The question is, which one should be the > "default" mode and which one should be subject to special constructs. You are not wrong. The above example will work fine in CL, though we usually (by convention, not requirement) use *'s around a variable that is 'special' (dynamically bound) so that people don't get confused. We would usually write: (defvar *x* 1) (defun y (a) (+ *x* 1)) (y 1) => 2 (let ((*x* 10)) (y 1)) => 11 Further, even a variable not defined with defvar can be on a one-time basis bound dynamically in CL by declaring it locally special. In this case, we still encourage *'s, but it's more common for that to be violated. e.g., (let ((x 1) (y 2)) (declare (special x y)) (eval '(+ x y))) => 3 Without the special declaration, this would signal an error since an x and y bound lexically would not be visible to eval. It would be easy for an elisp based on cl to offer a macro like: (defmacro dynamic-let (bindings &body forms) `(let ,bindings (declare (special ,@(mapcar #'car bindings))) ,@forms)) so that (dynamic-let ((x 1) (y 2)) (eval '(+ x y))) would expand to the previous 'let' expression, in the rare case that a defvar had not been done but a dynamic binding was still wanted.