all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: "Andreas Röhler" <andreas.roehler@online.de>
To: emacs-devel@gnu.org
Cc: Drew Adams <drew.adams@oracle.co>
Subject: Re: Default value of variables named `*-function' [was: Change in files.el]
Date: Wed, 1 Feb 2017 09:35:25 +0100	[thread overview]
Message-ID: <8e6ec9e5-d1db-843b-fbe8-45ed21b3e13d@online.de> (raw)
In-Reply-To: <82b4b3b7-ff61-42a7-b9fb-df3cc26a3f30@default>



On 31.01.2017 19:40, Drew Adams wrote:
>> I would appreciate the consistency of variables named
>> with -function/-predicate suffixes to have a function
>> has a default value. Being able to use add-function on
>> just variables is very convenient (I use it to tweak
>> region-extract-function). The default values also serve
>> as good examples.
> My comment here is not about providing an implicit/automatic
> default value.  (I doubt that that is needed or a good idea,
> but I could be wrong.)
>
> My comment is that the default value for a given variable
> whose value is intended to be a (single) function _should
> usually_ be function `ignore'.  Not implicitly (see previous
> paragraph) but explicitly: (defvar foo-function 'ignore).
>
> TL;DR:
> Start `-function' vars out with value `ignore', possibly
> advised, so `remove-function' can get you back to a no-op.
>
> But please read on...
>
> If the default value needs to be a function that does
> something (which is common), then instead of using, as
> the default value, the function that provides the default
> behavior, use `ignore' as the default value AND advise it
> immediately with the function that provides the default
> behavior.
>
> Why?  Because then you can use `remove-function' to get
> a no-op.  You need not set or bind the variable to
> 'ignore' to do that; just repeated `remove-function'
> will get you to the no-op `ignore'.
>
> `remove-function' is analogous to setting a cons-valued
> variable to its cdr.  If `(cdr (last xs))' is not nil
> then xs is not a true list (it is dotted).  Using
> `ignore' as the starting point for function advice is like
> using () as the starting point (the last cdr) of a list.
> Function  `ignore' is more or less to advice what () is to
> a list of functions - an identity element.
>
> Advising the function that is the value of a `*-function'
> variable gives you the possibility of, in effect,
> applying any number of functions.  Using `:after-while'
> or `:before-until', for example, gives you much the same
> effect as you get with a normal or abnormal hook (as
> opposed to a `*-function' hook).
>
> But there is this big difference between a hook whose
> value is a list of functions (a la `add-hook') and a
> `*-function' variable whose value is a function that is
> advised with, say, `:after-while':
>
> With a hook that is a list of functions, you can remove
> them all using `remove-hook'.  With an advised function,
> the value is always a function.  You can of course
> change the value to `ignore', but you cannot, just using
> `remove-function', get to a no-op function.
>
> Unless, that is, the starting point (the default value)
> is `ignore'.  Hence my suggestion: Start with `ignore',
> advising it immediately if some default behavior is
> called for.
>
> That lets users and code use just `add-function' and
> `remove-function' to get the effect they have with
> `add-hook' and `remove-hook': a (possibly empty)
> sequence of functions applied in order.
>
> I pointed this out in a parenthical remark in this post:
> http://lists.gnu.org/archive/html/emacs-devel/2016-10/msg00415.html
>
>      (Note that one difference from a hook is that a hook
>      does not privilege the first hook function in any way
>      (or the last, depending on how you look at it).
>      Removing advice is not equivalent to `remove-hook'.
>      It never "empties the hook" completely - the function
>      that was advised is still there after removal of all
>      advice.)
>
> Here's a case in point:
>
> Variable `isearch-filter-predicate' has a function value
> or nil.  This is legacy.  Users and code can still bind
> it or set it to nil.
>
> But they cannot set it to a list of functions.  IOW, it
> is basically a single-function variable (which would
> normally be named `*-function') - except for the ability
> to use nil instead.
>
> I have code that lets you (interactively) add to, remove
> from, etc. the behavior of `isearch-filter-predicate' on
> the fly.  For more info, see
> https://www.emacswiki.org/emacs/DynamicIsearchFiltering.
>
> You can hit a key to change the current filter predicate
> in ways like these:
>
> C-z -   Remove a predicate that you specify (default:
>          last-added predicate).
> C-z &   Add a predicate, AND-ing it as an `:after-while'
>          filter.
> C-z %   Add a predicate that requires search hits to
>          match a regexp you provide.
> C-z ||  Add a predicate, OR-ing it as a `:before-until'
>          filter.
> C-z |1  Replace the last-added filter by OR-ing it with
>          another.
> C-z ~~  Complement the overall filter predicate.
> C-z ~1  Replace the last-added filter by its complement.
> C-z !   Set the overall filter predicate.
> C-z 0   Reset the overall filter predicate to its default
>          value (`isearch-filter-visible').
> C-z c   Add a predicate that limits search between two
>          columns that you specify.
> C-z @   Add a predicate that constrains searching within a
>          given distance of (near) another search pattern
>          (you specify the distance and pattern).
>
> Since the default value of `isearch-filter-predicate' is
> not `ignore' but `isearch-filter-visible', you cannot just
> add and remove advice to get a no-op behavior or a behavior
> that is not a modification of `isearch-filter-visible'.
> Instead, you must set (or bind) `isearch-filter-predicate'.
>
> This is a defect, resulting from legacy: (1) using nil
> instead of `ignore' as the no-op filter and (2) using
> `isearch-filter-visible' instead of `ignore' as the
> default filter.
>
> It would be nice to be able to just add & remove advice,
> to control the behavior.  But that always acts on
> function `isearch-filter-visible', not on `ignore'.
>
> Code should of course be _able_ to set or bind the
> variable value - no question about that.  But things
> are more flexible if you can _also_ do pretty much
> anything to modify the behavior using just advice.
>
> If my suggestion were applied to the case of
> `isearch-filter-predicate' then (1) it would be renamed
> (e.g., to `isearch-filter-function'), and (2) its
> default value would be `ignore'.
>
> Now, because `isearch-filter-predicate' is legacy,
> (1) the variable renaming would need to deprecate (but
> continue to support) the old name, and (2) the variable
> value nil would need to continue to be supported.
>
> This is just an example, to try to get across the
> suggestion that (1) we use `ignore' as the (explicit,
> not automatic/implied) default value of variables named
> `*-function', and (2) for any such variable whose
> default behavior needs to be a no-op, we immediately
> (i.e., by default) advise it to provide that default
> behavior.
>
> That gives users & code two ways to change it to a no-op:
> (a) set the variable value to `ignore' or (b) remove all
> advice from the default function (`ignore').
>
> In a way, this amounts to saying that what is said
> (correctly) in (elisp) `Advice combinators' about
> various kinds of advice being "comparable for
> single-function hooks to (add-hook..." is not also true
> for `remove-function' - unless the starting point is
> function `ignore'.  Repeatedly applying `remove-hook'
> will eventually get you to (), but repeatedly applying
> `remove-function' will not get you to `ignore', unless...
>
> You might point out that if a user or code _does_ just
> set the value of such a variable to some other function
> than `ignore' then `remove-function' will _not_ get back
> to `ignore'.  Clearly.  The effect of setting or (with a
> little more work) binding can be had using just advice,
> but nothing prevents someone from not using advice to
> change the value.
>
> Dunno whether I was clear or I am missing something
> important.  But WDOT?
>

+1

OTOH wondering if not a simple customizable listing of 
buffers-not-to-save/query would deliver all needed.
Reading doc-string of optional arg PRED -- isn't that already kind of 
over-engineered?



  reply	other threads:[~2017-02-01  8:35 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-28  2:16 Change in files.el Richard Stallman
2017-01-28  2:46 ` Stefan Monnier
2017-01-28  9:10   ` Eli Zaretskii
2017-01-28 14:40     ` Stefan Monnier
2017-01-28 14:57       ` Eli Zaretskii
2017-01-28 15:31         ` Dmitry Gutov
2017-01-28 16:12           ` Eli Zaretskii
2017-01-28 15:40         ` Stefan Monnier
2017-01-28 16:08           ` Eli Zaretskii
2017-01-28 16:51             ` Stefan Monnier
2017-01-28 17:11               ` Eli Zaretskii
2017-01-28 17:22                 ` Stefan Monnier
2017-01-28 17:30                   ` Eli Zaretskii
2017-01-28 17:42                     ` Stefan Monnier
2017-01-28 17:53                       ` Eli Zaretskii
2017-01-29 18:59                         ` John Wiegley
2017-01-30  3:57                           ` Leo Liu
2017-01-30 15:58                             ` John Wiegley
2017-01-31  4:19                               ` Leo Liu
2017-01-31 14:01                                 ` John Wiegley
2017-01-31 14:46                               ` Stefan Monnier
2017-01-31 16:21                                 ` Kaushal Modi
2017-01-31 18:40                                   ` Default value of variables named `*-function' [was: Change in files.el] Drew Adams
2017-02-01  8:35                                     ` Andreas Röhler [this message]
2017-01-28 18:41                       ` Change in files.el Mark Oteiza
2017-01-28 19:37                         ` Eli Zaretskii
2017-02-01  3:49                           ` Mark Oteiza
2017-02-01  7:33                             ` Clément Pit-Claudel
2017-02-01 12:56                               ` Eli Zaretskii
2017-02-01 14:12                                 ` Kaushal Modi
2017-01-29  0:21       ` Richard Stallman
2017-02-04  9:18 ` Eli Zaretskii
2017-02-04 23:52   ` Richard Stallman

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=8e6ec9e5-d1db-843b-fbe8-45ed21b3e13d@online.de \
    --to=andreas.roehler@online.de \
    --cc=drew.adams@oracle.co \
    --cc=emacs-devel@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.