From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.help Subject: Re: Is add-to-list supposed to work when lexical-binding is t? Date: Wed, 05 Jun 2013 20:42:54 -0400 Message-ID: References: <1370473929.92379.YahooMailClassic@web141101.mail.bf1.yahoo.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1370479417 14367 80.91.229.3 (6 Jun 2013 00:43:37 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 6 Jun 2013 00:43:37 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Jun 06 02:43:37 2013 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UkOIh-0003t5-Bs for geh-help-gnu-emacs@m.gmane.org; Thu, 06 Jun 2013 02:43:35 +0200 Original-Received: from localhost ([::1]:52358 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UkOIg-0003P7-SG for geh-help-gnu-emacs@m.gmane.org; Wed, 05 Jun 2013 20:43:34 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:43216) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UkOIV-0003Op-BI for help-gnu-emacs@gnu.org; Wed, 05 Jun 2013 20:43:25 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UkOIU-0005uB-AN for help-gnu-emacs@gnu.org; Wed, 05 Jun 2013 20:43:23 -0400 Original-Received: from plane.gmane.org ([80.91.229.3]:38676) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UkOIU-0005tA-3k for help-gnu-emacs@gnu.org; Wed, 05 Jun 2013 20:43:22 -0400 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1UkOIP-0003dM-Qx for help-gnu-emacs@gnu.org; Thu, 06 Jun 2013 02:43:17 +0200 Original-Received: from 69-165-139-76.dsl.teksavvy.com ([69.165.139.76]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 06 Jun 2013 02:43:17 +0200 Original-Received: from monnier by 69-165-139-76.dsl.teksavvy.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 06 Jun 2013 02:43:17 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 75 Original-X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: 69-165-139-76.dsl.teksavvy.com User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) Cancel-Lock: sha1:yWnMUPt6tTeCv0TovzKsA073XQM= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:91338 Archived-At: >>> Section 11.9.3 (Lexical Binding) in the manual says "functions like >>> `symbol-value', `boundp', and `set' only retrieve or modify >>> a variable's dynamic binding". Why? Actually, the answer is much simpler: all the above are *functions* (as opposed to macros or special forms), so they receive values as arguments and know very little from their caller other than the values it passed as arguments. In order to do what you'd want them to do, they'd have to look at the value of variables in the scope of their caller. This is exactly what dynamic scoping provides, and is what lexical scoping prevents. >> With lexical scoping, a given variable name can have many different >> values at the same time so this is not an option. > I read the last bit as, "with lexical scoping, a given symbol (symbolic > name) can be interpreted as many different variables in different scopes > (and each variable can have multiple instances) ...", to synchronize > terminology. And I call the things that variables are bound to "instances", > not "bindings" like the docs do. *at the same time* is the important part. With dynamic scoping, only one of the various scopes exists at a given time. But with lexical scoping it's a bit more tricky: (let ((funs (mapcar (lambda (x) (lambda (y) (+ x y)) '(1 2 3)))) (mapcar (lambda (f) (funcall f 3)) funs)) this should return (4 5 6). Between the two mapcars, we have stored in `funs' 3 functions (more specifically closures), each one of them of the kind (lambda (y) (+ x y)). They each have their own copy of `x', so all three copies of `x' exist at the same time in `funs'. > In the scope of (let ((x 'a)) ...) with lexical binding enabled, since the > symbol x is interpreted as a lexical variable rather than as the global > variable (the latter bound to the global instance, the value cell for the > symbol x), I propose a quote-lex special form, where (quote-lex x), with > e.g. "&x" or maybe "^x" as readable syntax, returns a reference to the > current instance You can definitely do that. In the current Emacs sources it's provided under the name `gv-ref', which indeed works like C's &. > Then you could use argument-mutating functions, including the standard > add-to-list function, without having to convert them into macros, and do > e.g.: > (let ((x '(a))) (add-to-list &x 'b) x) -> (b a) We can definitely make add-to-list work for (let ((x '(a))) (add-to-list (gv-ref x) 'b) x) ===> (b a) That's easy and would work fine. But (gv-ref x) is not the same as 'x and trying to magically turn one into the other, while feasible in a few particular cases is simply impossible in general. >>> (let ((x '(a))) (add-to-list 'x 'b) x) -> (b a) >> Yup, this is asking for trouble. Use `push' or `cl-pushnew' instead. > So, converting every argument-mutating function into a macro actually _is_ > the right thing to do? Yes, pretty much. > That seems unnecessarily complicated, just a way of working around the > lack of lexical quoting. There is no "lack of lexical quoting", as seen above. Argument-mutating functions are relatively rare and using macros tends to be a lot more efficient than using gv-ref, so in most cases using macros makes more sense, despite their well known disadvantages. Stefan