* Re: let vs. buffer local bindings
2002-05-10 14:21 let vs. buffer local bindings Kim F. Storm
@ 2002-05-10 13:22 ` Gareth Owen
2002-05-10 13:48 ` Dave Pearson
2002-05-10 14:53 ` Kim F. Storm
2002-05-10 13:32 ` Andreas Schwab
2002-05-10 19:15 ` Stefan Monnier
2 siblings, 2 replies; 10+ messages in thread
From: Gareth Owen @ 2002-05-10 13:22 UTC (permalink / raw)
Cc: Dave Pearson, Kim F. Storm
storm@cua.dk (Kim F. Storm) writes:
> Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
> interference between let and buffer local bindings.
>
> Does anyone care to comment on the following result:
It should be noted that this seems only to be the case with 20.7.
Behaviour is more comprehensible in 21.1
--
Gareth Owen
"Computer games don't affect kids, I mean if Pac Man affected us as kids,
we'd all be running around in darkened rooms, munching pills and listening
to repetitive music."
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 14:21 let vs. buffer local bindings Kim F. Storm
2002-05-10 13:22 ` Gareth Owen
@ 2002-05-10 13:32 ` Andreas Schwab
2002-05-10 15:31 ` Kim F. Storm
2002-05-10 19:15 ` Stefan Monnier
2 siblings, 1 reply; 10+ messages in thread
From: Andreas Schwab @ 2002-05-10 13:32 UTC (permalink / raw)
Cc: emacs-devel, Dave Pearson, Gareth Owen
storm@cua.dk (Kim F. Storm) writes:
|> Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
|> interference between let and buffer local bindings.
*Note Introduction to Buffer-Local Variables: (elisp)Intro to
Buffer-Local.
*Warning:* When a variable has buffer-local values in one or more
buffers, you can get Emacs very confused by binding the variable with
`let', changing to a different current buffer in which a different
binding is in effect, and then exiting the `let'. This can scramble
the values of the buffer-local and default bindings.
To preserve your sanity, avoid using a variable in that way. If you
use `save-excursion' around each piece of code that changes to a
different current buffer, you will not have this problem (*note
Excursions::).
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 13:22 ` Gareth Owen
@ 2002-05-10 13:48 ` Dave Pearson
2002-05-10 14:53 ` Kim F. Storm
1 sibling, 0 replies; 10+ messages in thread
From: Dave Pearson @ 2002-05-10 13:48 UTC (permalink / raw)
Cc: emacs-devel, Kim F. Storm
* Gareth Owen <usenet@gwowen.freeserve.co.uk> [2002-05-10 14:22:31 +0100]:
> storm@cua.dk (Kim F. Storm) writes:
>
> > Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
> > interference between let and buffer local bindings.
> >
> > Does anyone care to comment on the following result:
>
> It should be noted that this seems only to be the case with 20.7.
> Behaviour is more comprehensible in 21.1
The (0 1 3 4) result (which seems wrong) happens in 21.2.
--
Dave Pearson
http://www.davep.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* let vs. buffer local bindings
@ 2002-05-10 14:21 Kim F. Storm
2002-05-10 13:22 ` Gareth Owen
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Kim F. Storm @ 2002-05-10 14:21 UTC (permalink / raw)
Cc: Dave Pearson, Gareth Owen
Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
interference between let and buffer local bindings.
Does anyone care to comment on the following result:
First try evalling:
(progn
(make-variable-buffer-local 'foo)
(setq-default foo 1)
(list foo
(let ((foo 2) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)
(let ((foo 3) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)
(let ((foo 4) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)))
which produces what seems to be correct:
(1 2 3 4)
But now eval this:
(progn
(setq foo 0)
(list foo
(let ((foo 2) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)
(let ((foo 3) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)
(let ((foo 4) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)))
which produces what seems to be wrong:
(0 1 3 4)
--
Kim F. Storm <storm@cua.dk> http://www.cua.dk
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 13:22 ` Gareth Owen
2002-05-10 13:48 ` Dave Pearson
@ 2002-05-10 14:53 ` Kim F. Storm
1 sibling, 0 replies; 10+ messages in thread
From: Kim F. Storm @ 2002-05-10 14:53 UTC (permalink / raw)
Cc: emacs-devel, Dave Pearson
Gareth Owen <usenet@gwowen.freeserve.co.uk> writes:
> storm@cua.dk (Kim F. Storm) writes:
>
> > Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
> > interference between let and buffer local bindings.
> >
> > Does anyone care to comment on the following result:
>
> It should be noted that this seems only to be the case with 20.7.
> Behaviour is more comprehensible in 21.1
My results are from the latest CVS emacs (aka 21.4), so there's still
something to explain :-)
--
Kim F. Storm <storm@cua.dk> http://www.cua.dk
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 13:32 ` Andreas Schwab
@ 2002-05-10 15:31 ` Kim F. Storm
0 siblings, 0 replies; 10+ messages in thread
From: Kim F. Storm @ 2002-05-10 15:31 UTC (permalink / raw)
Cc: emacs-devel, Dave Pearson, Gareth Owen
Andreas Schwab <schwab@suse.de> writes:
> storm@cua.dk (Kim F. Storm) writes:
>
> |> Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
> |> interference between let and buffer local bindings.
>
> *Note Introduction to Buffer-Local Variables: (elisp)Intro to
> Buffer-Local.
>
> *Warning:* When a variable has buffer-local values in one or more
> buffers, you can get Emacs very confused by binding the variable with
> `let', changing to a different current buffer in which a different
> binding is in effect, and then exiting the `let'. This can scramble
> the values of the buffer-local and default bindings.
>
> To preserve your sanity, avoid using a variable in that way. If you
> use `save-excursion' around each piece of code that changes to a
> different current buffer, you will not have this problem (*note
> Excursions::).
>
I see.
But I had got the impression that the following changes to specbind
were supposed to remove that limitation.... I'm obviously mistaken:
2001-07-05 Gerd Moellmann <gerd@gnu.org>
* eval.c (specbind): Additionally record the buffer that was
current when a buffer-local or frame-local variable was bound.
2001-07-03 Gerd Moellmann <gerd@gnu.org>
* eval.c (specbind): If SYMBOL has a frame-local binding, record
the frame on the binding stack. Change format of entries for
local bindings on the binding stack to '(SYMBOL . WHERE)'.
(unbind_to): Handle unbinding a frame-local variable.
--
Kim F. Storm <storm@cua.dk> http://www.cua.dk
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 14:21 let vs. buffer local bindings Kim F. Storm
2002-05-10 13:22 ` Gareth Owen
2002-05-10 13:32 ` Andreas Schwab
@ 2002-05-10 19:15 ` Stefan Monnier
2002-05-10 22:14 ` Kim F. Storm
2 siblings, 1 reply; 10+ messages in thread
From: Stefan Monnier @ 2002-05-10 19:15 UTC (permalink / raw)
Cc: emacs-devel, Dave Pearson, Gareth Owen
> Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
> interference between let and buffer local bindings.
Gerd has fixed one of the bad interactions between buffer-local and let-bound
variables, but we can't fix them all. Or at least, I think that fixing
them such that there's a clear semantics will mean changing the current
semantics in a way that would break compatibility.
Currently, (let ((x val)) body) is similar to something like
(push x)
(unwind-protect
(progn
(setq x val)
body)
(setq x (pop)))
And similarly, `set-buffer' works by changing the "current"
value of all its local variables. So in your example you get:
(progn
`foo' is local in the buffer. Its global value is 1.
(setq foo 0)
The local value is now 0.
(list foo
So you get 0 for the first elem of the list.
(let ((foo 2) (buf (generate-new-buffer "baz")))
the current value of foo is now set to 2 (note that the current value
right now is the value in the local buffer).
(set-buffer buf) foo)
`foo' because foo is local in the current buffer but not in `baz',
its current value is changed to the one in `baz' which is the global value
(i.e. 1) so you get 1 as the second elem of the list.
At the end, the buffer-local value in the original buffer is reset
from 2 back to 0. Before Gerd's fix (i.e. in Emacs<21) it would
have "reset" the current value instead, thus changing the global value
from 1 to 0.
(let ((foo 3) (buf (generate-new-buffer "baz")))
Now the current value (i.e. the global value) is set to 3.
(set-buffer buf) foo)
When switching buffer, we're now sitching between two buffers where
foo is both times global, so foo's value is not changed. We thus
get 3 and at the end, the global value is reset to 1.
(let ((foo 4) (buf (generate-new-buffer "baz")))
(set-buffer buf) foo)))
I think by now you now how this works. These semantics are pretty
ugly and basically "defined by the implementation" with a very
operational feeling to them. Not declarative at all. Another
problem with it is that it relies on assignments, which means that
it would interact very poorly with concurrency (while inside
(let ((newvar 1)) ...) another thread would see that the global value
of `newvar' is 1 instead of being unbound.
I think a good practice is to use with-current-buffer rather than set-buffer
because it avoids the most surprising cases (such as the one in your example).
Stefan
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 19:15 ` Stefan Monnier
@ 2002-05-10 22:14 ` Kim F. Storm
2002-05-12 16:34 ` Richard Stallman
0 siblings, 1 reply; 10+ messages in thread
From: Kim F. Storm @ 2002-05-10 22:14 UTC (permalink / raw)
Cc: emacs-devel, Dave Pearson, Gareth Owen
"Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes:
> > Gareth Owen <usenet@gwowen.freeserve.co.uk> has found a peculiar
> > interference between let and buffer local bindings.
>
> Gerd has fixed one of the bad interactions between buffer-local and let-bound
> variables, but we can't fix them all. Or at least, I think that fixing
> them such that there's a clear semantics will mean changing the current
> semantics in a way that would break compatibility.
Thanks Stefan.
I understand what's going on now.
Considering that Gerd's fix has indeed improved emacs's behaviour in
this area, I think we need to change the elisp manual to reflect this.
Specifically, the following warning:
*Warning:* When a variable has buffer-local values in one or more
buffers, you can get Emacs very confused by binding the variable with
`let', changing to a different current buffer in which a different
binding is in effect, and then exiting the `let'. This can scramble
the values of the buffer-local and default bindings.
should be reworded into something less dramatic, e.g.
*Warning:* When a variable has buffer-local values in one or
more buffers, binding the variable with `let' and changing to a
different current buffer in which a different binding is in
effect, and then exiting the `let', the variable may not be
restored to the value it had before the let.
Also, the example illustrating this is no longer valid, as the value of foo
is correct when we return to buffer "a", ie. the example should read:
(setq foo 'b)
(set-buffer "a")
(make-local-variable 'foo)
(setq foo 'a)
(let ((foo 'temp))
;; foo => 'temp ; let binding in buffer "a"
(set-buffer "b")
;; foo => 'b ; the global value since foo is not local in "b"
BODY...)
foo => 'b ; we are still in buffer "b", but exiting the let
; restored the local value in buffer "a"
(set-buffer "a") ; which can be seen here:
foo => 'a ; we are back to the local value in buffer "a"
--
Kim F. Storm <storm@cua.dk> http://www.cua.dk
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-10 22:14 ` Kim F. Storm
@ 2002-05-12 16:34 ` Richard Stallman
2002-05-13 20:07 ` Kim F. Storm
0 siblings, 1 reply; 10+ messages in thread
From: Richard Stallman @ 2002-05-12 16:34 UTC (permalink / raw)
Cc: monnier+gnu/emacs, emacs-devel, davep.news, usenet
Could you possibly edit the manual text? It is in variables.texi.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: let vs. buffer local bindings
2002-05-12 16:34 ` Richard Stallman
@ 2002-05-13 20:07 ` Kim F. Storm
0 siblings, 0 replies; 10+ messages in thread
From: Kim F. Storm @ 2002-05-13 20:07 UTC (permalink / raw)
Cc: emacs-devel
Richard Stallman <rms@gnu.org> writes:
> Could you possibly edit the manual text? It is in variables.texi.
Done.
--
Kim F. Storm <storm@cua.dk> http://www.cua.dk
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2002-05-13 20:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-05-10 14:21 let vs. buffer local bindings Kim F. Storm
2002-05-10 13:22 ` Gareth Owen
2002-05-10 13:48 ` Dave Pearson
2002-05-10 14:53 ` Kim F. Storm
2002-05-10 13:32 ` Andreas Schwab
2002-05-10 15:31 ` Kim F. Storm
2002-05-10 19:15 ` Stefan Monnier
2002-05-10 22:14 ` Kim F. Storm
2002-05-12 16:34 ` Richard Stallman
2002-05-13 20:07 ` Kim F. Storm
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).