unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Kelly Dean <kelly@prtime.org>
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: emacs-devel@gnu.org
Subject: Re: [PATCH] (Updated) Run hook when variable is set
Date: Sat, 14 Feb 2015 22:19:45 +0000	[thread overview]
Message-ID: <p9mojYt9E8Qm0AaRz0waS74hDhNX6aGAfzT2W7kd4K6@local> (raw)
In-Reply-To: <jwvh9upl54a.fsf-monnier+emacs@gnu.org>

Stefan Monnier wrote:
>> The docstring for symbol-setter-function says lexical binding is required
>> for the hook function,
>
> I don't think that's true, BTW.  I agree it's recommended (I recommend
> using lexical-binding for all new code), but other than that it should
> work just fine with dynamically scoped code.

It was to enable the standard function to always just return newval, even if it's Qunbound. Works for lexical binding (the interpreter doesn't barf), but not for dynamic. But that doesn't matter anymore, since you said I need to use a different way of handling Qunbound.

>> The docstring already says to use :before if you just need to watch
>> variables,
>
> It shouldn't either.  This issue of which kind of advice to use is not
> specific to this variable, so there's no need to put it there.

It's an unusual function. The effect of overriding the return value, and interaction with «let», and how to deal with the case of makunbound, all need to be documented somewhere, and for completeness, it makes sense for the documentation to also cover the case of not overriding the return value. If not in the docstring, then maybe in the manual?

> Actually I don't see these as two independent elements combined
> into one.  I see it as a single value with 3 levels:
> - any write you want
> - write vetted by Elisp code
> - no write at all

If there's just :before advice (e.g. a profiler), then the write is not vetted.

> We could even drop the last setting and implement it in Elisp via
> symbol-setter-function, except that it's currently used for variables
> where we'd rather not give Elisp the opportunity to allow writes.

Yeah, changing the value of t or nil would be quite fun. ;-)

>> +DEFUN ("void-p", Fvoid_p, Svoid_p, 1, UNEVALLED, 0,
[snip]
> I doubt this works on lexical-vars in compiled code.  Why do we need it?

It was to enable checking for Qunbound for lexical newval and oldval in symbol-setter-function.

I've removed it.

> So far we've been extra careful to try and make sure Qunbound doesn't
> escape into Elisp world.  I don't think we want to reconsider this
> design choice, since adding this Qunbound as a "normal" value in Elisp
> will just create the need for another special "really unbound" value.

Qunbound already escapes: you just have to use makunbound instead of «set» to set it, and boundp instead of symbol-value to read it. Lexical variables are second-class because they can't be set to all the values that dynamic variables can be; the purpose of my «void» function was to fix that.

Of course, you'll say makunbound doesn't set a value; it unbinds the variable. But that's not true! For example, consider this:
(defvar foo 0)
(defvar bar 1)
(let ((foo 2)) bar) → 1
(let ((foo 2)) (makunbound 'foo) foo) → Lisp error: (void-variable foo)
foo → 0

In the dynamic environment created by the first «let», foo is bound, but bar is not bound. Therefore an attempt to read the not-bound bar within that environment will look in outer environments until it finds bar bound in one of them. An error would occur if bar weren't bound in any of those outer environments, not even the global one.

In the environment created by the second «let», foo is first bound to 2. If it were unbound, then an attempt to read it would return 0, for the same reason that an attempt to read bar in the first environment returns 1. So what does makunbound do? If it really unbound foo, then the subsequent attempt to read foo would return 0, because foo would be not bound in the dynamic environment. But in fact the attempt to read foo returns Qunbound, which was the value set by makunbound, and the interpreter barfs because you didn't use the special function boundp to read that special value. IOW, Qunbound escapes into the Lisp world.

Then when the «let» exits, the dynamic environment is destroyed, which actually _does_ unbind foo (from Qunbound). So now, the attempt to read foo returns 0, because global foo is no longer shadowed by the dynamic binding of foo to the value Qunbound.

I agree that setting lexicals to Qunbound is absurd. «void» was just to enables lexicals and dynamics to be set to the same values. My point is that letting Qunbound escape into the Lisp world in the first place is also absurd. (CL does it too.) Makunbound should actually make a variable be unbound, not bind it to some special value that triggers an error (and lies about the cause) when you try to read it. Because it makes no sense to actually unbind a dynamic or lexical variable except by destruction of the environment in which the variable occurs, this means makunbound should apply only to global variables.

Because global variables don't shadow anything, binding them to Qunbound is the same as unbinding them so far as Lisp code is concerned, so this implementation detail doesn't escape. And Lisp doesn't let you bind lexicals to Qunbound, so they don't have a problem either. But it _does_ let you bind dynamic variables to Qunbound (and Elisp lets you bind buffer-locals to Qunbound too), which is a problem because they shadow variables in outer environments. I know it's officially been a feature for a long time. But a bug by any other name is still a bug.

I've removed «void». I recommend making makunbound stop working on non-globals too.

> I see some alternatives:
[snip]
> - OLDVAL is either a list of one element containing the old value, or
>   nil (when that old value is Qunbound).

Then run_varhook must cons. That'll generate a lot of garbage if you use it for profiling, or for debugging in a way where you don't just pause to inspect every hooked variable. Is that ok?

> - Use a special value to represent "unbound", e.g. a special keyword like
>   `::value--unbound::'.

Then varhook would be defective. If the hook function returns a special keyword to represent Qunbound (to avoid blocking makunbound), then just hooking unavoidably changes the behavior of Emacs (because it's impossible to set a hooked variable to that keyword), which is the wrong thing to do.

Of course, telling the hook function that a variable is bound to Qunbound without having to cons is easy (could just pass an additional argument, t or nil). The problem is needing to _return_ Qunbound. If run_varhook will cons, then the hook function can just return nil to represent Qunbound, or do (setcar newval ...) and then return newval to set the variable to another value without needing yet another cons.

Or to avoid needing to cons in run_varhook, it could specbind something like Qsymbol_newval_void (to t if the new value is Qunbound), so the hook function could setq symbol-newval-void to t or nil to indicate whether to set the hooked variable to Qunbound. This way, run_varhook could pass the newval argument directly (as it currently does), without wrapping it, except pass nil as a dummy value if the new value is Qunbound. This is what I prefer, but if you don't want me to do it this way, then I'll wrap newval.

> Oh, and I think we can keep the name `constant' rather than use the
> verbose `constant_or_hooked'.  It's not perfect, but at least it reduces
> the patch's size and the number of lines that are too long.

Would ⌜const_hooked⌝ be ok? It's only 4 extra characters. Using ⌜constant⌝ for something that doesn't just mean «constant» is as gross as ⌜set-default⌝ for «set-global». As noted above, hooked doesn't imply vetted, so hooked doesn't mean sort-of-constant. Even if it did, ⌜constant⌝ is a misleading term for something that can be sort-of-constant; ⌜constantness⌝ would be better, since the term allows for the possibility of a range of values. If it's too long, ⌜constness⌝ is only 1 extra character.

The patch is big, but it'll just be a one-time change to the source code. After that, nobody reading the code will care what the patch was, and everybody will be stuck with the misleading name if it isn't changed.



  reply	other threads:[~2015-02-14 22:19 UTC|newest]

Thread overview: 110+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-20  2:54 Proposal to change cursor appearance to indicate region activation Kelly Dean
2013-04-20  7:23 ` Drew Adams
2015-01-22  5:38   ` [PATCH] " Kelly Dean
2015-01-22 14:25     ` Stefan Monnier
2015-01-23  3:08       ` [PATCH] " Kelly Dean
2015-01-23  4:55         ` Stefan Monnier
2015-01-23 11:07           ` Kelly Dean
2015-01-23 17:49             ` Drew Adams
2015-01-24  3:06               ` Kelly Dean
2015-01-24  4:52                 ` Stefan Monnier
2015-01-24  9:22                   ` Kelly Dean
2015-01-25 14:29                     ` Stefan Monnier
2015-01-28  9:15                       ` [PATCH] Run hook when variable is set Kelly Dean
2015-01-28  9:23                         ` [PATCH] Proposal to change cursor appearance to indicate region activation Kelly Dean
2015-01-28 11:24                           ` David Kastrup
2015-01-28 12:13                             ` David Kastrup
2015-01-29 10:46                             ` Kelly Dean
2015-01-29 11:16                               ` David Kastrup
2015-01-30  7:20                                 ` Kelly Dean
2015-01-30  9:19                                   ` David Kastrup
2015-01-30 10:05                                     ` Kelly Dean
2015-01-30 10:12                                       ` David Kastrup
2015-01-30  9:43                                   ` Kelly Dean
2015-01-28 19:25                         ` [PATCH] Run hook when variable is set Stefan Monnier
2015-01-29  8:20                           ` Kelly Dean
2015-01-29  8:28                             ` Lars Ingebrigtsen
2015-01-29 14:58                             ` Stefan Monnier
2015-01-30  7:34                               ` Kelly Dean
2015-01-30 15:55                                 ` Stefan Monnier
2015-01-31  9:18                                   ` Kelly Dean
2015-01-31 20:48                                     ` Stefan Monnier
2015-02-02  5:40                                       ` Kelly Dean
2015-02-02 15:57                                         ` Stefan Monnier
2015-02-03 19:56                                           ` Kelly Dean
2015-02-03 22:49                                             ` Stefan Monnier
2015-02-05  3:10                                               ` [PATCH] (Updated) " Kelly Dean
2015-02-05 13:57                                                 ` Stefan Monnier
2015-02-06  5:34                                                   ` Kelly Dean
2015-02-06 14:42                                                     ` Stefan Monnier
2015-02-07 12:27                                                       ` Kelly Dean
2015-02-07 15:09                                                         ` Stefan Monnier
2015-02-09  3:24                                                           ` Kelly Dean
2015-02-12 19:58                                                             ` Stefan Monnier
2015-02-13 23:08                                                               ` Kelly Dean
2015-02-14  0:55                                                                 ` Stefan Monnier
2015-02-14 22:19                                                                   ` Kelly Dean [this message]
2015-02-15 20:25                                                                     ` Stefan Monnier
2015-02-17  2:22                                                                       ` Kelly Dean
2015-02-17 23:07                                                                         ` Richard Stallman
2015-02-18  3:19                                                                           ` The purpose of makunbound (Was: Run hook when variable is set) Kelly Dean
2015-02-18  5:48                                                                             ` The purpose of makunbound Stefan Monnier
2015-02-18  8:51                                                                               ` Kelly Dean
2015-02-18 14:34                                                                                 ` Stefan Monnier
2015-02-18 18:53                                                                                   ` Kelly Dean
2015-02-18 22:42                                                                                     ` Stefan Monnier
2015-02-19 10:36                                                                                       ` Kelly Dean
2015-02-22  0:18                                                                                   ` Kelly Dean
2015-02-19 10:45                                                                           ` Kelly Dean
2015-02-19 13:33                                                                             ` Stefan Monnier
2015-02-19 23:51                                                                               ` Kelly Dean
2015-02-20  1:59                                                                                 ` Stefan Monnier
2015-02-20  9:35                                                                                   ` Kelly Dean
2015-02-20 16:55                                                                                     ` Stefan Monnier
2015-02-20  2:58                                                                                 ` Stephen J. Turnbull
2015-02-20  0:56                                                                             ` Richard Stallman
2015-02-20  9:02                                                                               ` Kelly Dean
2015-02-20 15:41                                                                                 ` Richard Stallman
2015-02-21  5:45                                                                                   ` Stephen J. Turnbull
2015-02-22  0:32                                                                                     ` Kelly Dean
2015-02-22  8:45                                                                                       ` Andreas Schwab
2015-02-18  5:15                                                                         ` [PATCH] (Updated) Run hook when variable is set Kelly Dean
2015-02-18 22:37                                                                           ` Stefan Monnier
2015-02-18 22:37                                                                         ` Stefan Monnier
2015-02-19 10:35                                                                           ` Kelly Dean
2015-02-19 13:30                                                                             ` Stefan Monnier
2015-02-20  6:48                                                                               ` Kelly Dean
2015-02-20 19:29                                                                                 ` Stefan Monnier
2015-02-21 14:18                                                                                   ` Kelly Dean
2015-02-21 20:51                                                                                     ` Stefan Monnier
2015-02-22  0:32                                                                                       ` Kelly Dean
2015-02-22 10:40                                                                                         ` Stephen J. Turnbull
2015-02-22 21:35                                                                                         ` Stefan Monnier
2015-02-23  3:09                                                                                           ` Kelly Dean
2015-02-23  4:19                                                                                             ` Stefan Monnier
2015-02-20 20:27                                                                               ` Proposal for debugging/testing option Kelly Dean
2015-02-24 16:28                                                                                 ` Stefan Monnier
2015-02-14 20:37                                                               ` [PATCH] (Updated) Run hook when variable is set Johan Bockgård
2015-02-15 19:36                                                                 ` Stefan Monnier
2015-02-15 19:53                                                                   ` Patches: inline vs. attachment, compressed vs. uncompressed. [was: Run hook when variable is set] Alan Mackenzie
2015-02-06  9:55                                                   ` [PATCH] (Updated) Run hook when variable is set Kelly Dean
2015-01-30 23:29                                 ` [PATCH] " Richard Stallman
2015-01-31  9:23                                   ` Kelly Dean
2015-01-31 23:16                                     ` Richard Stallman
2015-02-02  5:41                                       ` Kelly Dean
2015-02-01  2:04                               ` Alexis
2015-02-01  4:05                                 ` Stefan Monnier
2015-02-01  8:58                                   ` David Kastrup
2015-01-29 16:06                             ` Eli Zaretskii
2015-01-30  7:14                               ` Kelly Dean
2015-01-30  9:08                                 ` Eli Zaretskii
2015-01-23 20:34             ` [PATCH] Proposal to change cursor appearance to indicate region activation Stefan Monnier
2015-01-24  0:25               ` Kelly Dean
2015-01-23 10:01         ` Tassilo Horn
2015-01-23 17:49           ` Drew Adams
2015-01-23 10:06         ` Eli Zaretskii
2015-01-23 11:40           ` Kelly Dean
2015-01-23 11:56             ` Eli Zaretskii
2015-01-22  5:41   ` Kelly Dean
2013-11-23 13:34 ` Stefan Monnier
2013-11-23 20:25   ` Drew Adams

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

  List information: https://www.gnu.org/software/emacs/

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

  git send-email \
    --in-reply-to=p9mojYt9E8Qm0AaRz0waS74hDhNX6aGAfzT2W7kd4K6@local \
    --to=kelly@prtime.org \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@IRO.UMontreal.CA \
    /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 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).