all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Stefan Monnier <monnier@iro.umontreal.ca>
To: help-gnu-emacs@gnu.org
Subject: Re: Is add-to-list supposed to work when lexical-binding is t?
Date: Wed, 05 Jun 2013 20:42:54 -0400	[thread overview]
Message-ID: <jwvobbkqe06.fsf-monnier+gmane.emacs.help@gnu.org> (raw)
In-Reply-To: 1370473929.92379.YahooMailClassic@web141101.mail.bf1.yahoo.com

>>> 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




  reply	other threads:[~2013-06-06  0:42 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-05 23:12 Is add-to-list supposed to work when lexical-binding is t? Kelly Dean
2013-06-06  0:42 ` Stefan Monnier [this message]
     [not found] <mailman.1450.1370998793.22516.help-gnu-emacs@gnu.org>
2013-06-13 14:57 ` Stefan Monnier
  -- strict thread matches above, loose matches on Subject: below --
2013-06-12  0:59 Kelly Dean
     [not found] <mailman.1311.1370828650.22516.help-gnu-emacs@gnu.org>
2013-06-10  5:12 ` Barry Margolin
2013-06-10  1:43 Kelly Dean
2013-06-10  7:56 ` Stefan Monnier
2013-06-04  0:42 Kelly Dean
2013-06-04  1:49 ` Stefan Monnier
2013-06-04 15:24   ` PJ Weisberg
2013-06-05  2:41     ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=jwvobbkqe06.fsf-monnier+gmane.emacs.help@gnu.org \
    --to=monnier@iro.umontreal.ca \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.