From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: =?UTF-8?Q?Andreas_R=c3=b6hler?= Newsgroups: gmane.emacs.devel Subject: Re: Default value of variables named `*-function' [was: Change in files.el] Date: Wed, 1 Feb 2017 09:35:25 +0100 Message-ID: <8e6ec9e5-d1db-843b-fbe8-45ed21b3e13d@online.de> References: <83mvebzh0k.fsf@gnu.org> <83bmurz0y9.fsf@gnu.org> <8360kzyxor.fsf@gnu.org> <83ziibxg7j.fsf@gnu.org> <83y3xvxfbs.fsf@gnu.org> <83wpdfxe96.fsf@gnu.org> <82b4b3b7-ff61-42a7-b9fb-df3cc26a3f30@default> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: blaine.gmane.org 1485937508 5972 195.159.176.226 (1 Feb 2017 08:25:08 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 1 Feb 2017 08:25:08 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux i686; rv:45.0) Gecko/20100101 Icedove/45.6.0 Cc: Drew Adams To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Feb 01 09:25:04 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cYqDv-0001GZ-6i for ged-emacs-devel@m.gmane.org; Wed, 01 Feb 2017 09:25:03 +0100 Original-Received: from localhost ([::1]:43240 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cYqE0-00040T-Ck for ged-emacs-devel@m.gmane.org; Wed, 01 Feb 2017 03:25:08 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:54731) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cYqDs-0003zJ-3R for emacs-devel@gnu.org; Wed, 01 Feb 2017 03:25:01 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cYqDn-0004Rh-4L for emacs-devel@gnu.org; Wed, 01 Feb 2017 03:25:00 -0500 Original-Received: from mout.kundenserver.de ([212.227.126.135]:63784) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cYqDm-0004Qv-PE for emacs-devel@gnu.org; Wed, 01 Feb 2017 03:24:55 -0500 Original-Received: from [192.168.178.35] ([77.12.189.14]) by mrelayeu.kundenserver.de (mreue003 [212.227.15.167]) with ESMTPSA (Nemesis) id 0MFwt0-1ceuVT3IOs-00EseO; Wed, 01 Feb 2017 09:24:42 +0100 In-Reply-To: <82b4b3b7-ff61-42a7-b9fb-df3cc26a3f30@default> X-Provags-ID: V03:K0:g/oXnFdHyREduJPgDs1Q/HouF0RLL6jZXCHR4wFZQQUqWysVIOO QRK4ElcQd8RehVz5X/ke4GPgHBObkAZUu/JE/Bm/DPnqhIKmdwwStFtPQ+WjwUa37ZHhSLA tu7oKp9rR1x9cu0XcSJrmH/c3Ad8ms9k/rv42G3bNp9q8OzJFktEBIxig9+pJ2NH7b4yqt2 Qk8z3DtgE7t4XmHAEGi7g== X-UI-Out-Filterresults: notjunk:1;V01:K0:dnVlHe2do8U=:y3QsmFndt2ozJwoFCXMqqY NgP/Rc+XZZBa9uKZk2nnb7iPbT1RpB16S/Rxg//zqPfPnECySw2SgWIObDtxz+KU4P1YEsGWn tqri47t6ZBSVkZ2X6aWxmevze5jiEdBqLcPr3EQjGDRNAw5bwSMU7WzznXsZTRm7ud0ZCRi8B zj/FuYdLA17llfp+VBIko7Q4Osfvbv1fPCOvM6SGX8lzuu8Cm/2Vtm56AN47mvhr+z2Kk8IKN vuCiB/ptw4+CEXUWAycPiZRawfN6xdU9ngs6qzxbzlysCeqq1CPcTx3cQ6zblyWdr/ks4yeyh Qz/qkT2F6e5KReeELyrGMz/6B3ve1iYk/ONnP6T/O6Ac7fqbNBe9jneF+X/x2+XF3dHjFl8IQ C1jHCAhDTfUKwJSNEbFGcnUAldq189D67PrS3L9oAPyU8wn4f9gipTQSqL9y/pPFr5mbu7WBs TmQOooclj166W5Ls2cIp8l4BlMpnrUKU0ASwDhw3j3/zWpFDoQdaA3fWA5P5QHW9+XA4J1nGb pypIO5cL8/d16LRPdIlNWtuNWNRrPWBgVMDlVhwJebSXo0NzfBPsNzPtxpnvKipbFy068LEgp SfWIpzp+fXSsTeDvy8HPMREUjuNhn3sdwHGY2caZhcmXiAn8Xq5pE9EQQoWRv6qTwI7PWyB5c j/xiBYd84EbST2yTDYd0bxuVGGB3ety46o3b6laOzq4+lnvuDk7GOj/35sAdipFIcpkt9Fwe9 L2bIZ3vmEgYAdlxe X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.126.135 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:211831 Archived-At: 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?