From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Drew Adams Newsgroups: gmane.emacs.bugs Subject: bug#34708: alist-get has unclear documentation Date: Mon, 11 Mar 2019 10:48:16 -0700 (PDT) Message-ID: <6e0c5a88-34db-4957-9cc5-98a14ae64f9f@default> References: <87wolhr5k6.fsf@web.de> <87y35xdu4w.fsf@web.de> <87mumcdu7f.fsf@web.de> <875zsyhakx.fsf@ericabrahamsen.net> <87fts2h9we.fsf@web.de> <871s3mh85d.fsf@ericabrahamsen.net> <874l8iebyz.fsf@web.de> <878sxui7bo.fsf@ericabrahamsen.net> <87va0xcxco.fsf@web.de> <87h8chey12.fsf@ericabrahamsen.net> <60367f47-c0b0-45b4-8ccf-169044400a75@default> <8736ntmsy3.fsf@web.de> <3af3b645-84e0-4208-be48-810e8cd2cfa8@default> <87wol5l6xk.fsf@web.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="171488"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Eric Abrahamsen , 34708@debbugs.gnu.org To: Michael Heerdegen Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Mar 11 18:59:36 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1h3PD2-000iFZ-Am for geb-bug-gnu-emacs@m.gmane.org; Mon, 11 Mar 2019 18:59:32 +0100 Original-Received: from localhost ([127.0.0.1]:37839 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3PD1-0007vG-6k for geb-bug-gnu-emacs@m.gmane.org; Mon, 11 Mar 2019 13:59:31 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:45624) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3PCj-0007Et-On for bug-gnu-emacs@gnu.org; Mon, 11 Mar 2019 13:59:15 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h3P2s-00069r-Su for bug-gnu-emacs@gnu.org; Mon, 11 Mar 2019 13:49:04 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:54141) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h3P2s-00069g-M5 for bug-gnu-emacs@gnu.org; Mon, 11 Mar 2019 13:49:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1h3P2s-0006XR-E0 for bug-gnu-emacs@gnu.org; Mon, 11 Mar 2019 13:49:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Drew Adams Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 11 Mar 2019 17:49:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 34708 X-GNU-PR-Package: emacs Original-Received: via spool by 34708-submit@debbugs.gnu.org id=B34708.155232651025085 (code B ref 34708); Mon, 11 Mar 2019 17:49:02 +0000 Original-Received: (at 34708) by debbugs.gnu.org; 11 Mar 2019 17:48:30 +0000 Original-Received: from localhost ([127.0.0.1]:39452 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h3P2L-0006WV-NM for submit@debbugs.gnu.org; Mon, 11 Mar 2019 13:48:30 -0400 Original-Received: from userp2120.oracle.com ([156.151.31.85]:52620) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h3P2K-0006WI-3b for 34708@debbugs.gnu.org; Mon, 11 Mar 2019 13:48:28 -0400 Original-Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x2BHhcsq153142; Mon, 11 Mar 2019 17:48:21 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=mime-version : message-id : date : from : sender : to : cc : subject : references : in-reply-to : content-type : content-transfer-encoding; s=corp-2018-07-02; bh=3WZnMijpXpWrAP/ASkoRFZ+HtmgAxXCoRm7SMI+RbJA=; b=1C+RGcm4KzbJviixU5ZeqTqF7Cg9fFfEqnTfKt/RqMn5fLo+RmVgDbFApAG4ATK3xa7s xuhZcVe/1d5aheB0Qs/Y1LGP7EQPmFaXARrM6sid9ui2YEumoSRkI4mO8VGdRTj2Vx+x f2+aHn8aMdW2xYzIbbMXCH17H4gHWikSIeE6eR803epyU8K1HaZ/HozhNI8p2Cz4xOvd XU7fxDIMynbEfgxqcCvsTwIWMU5pxqqSHyZ7AzLQs+rTXw8qKCjwbLWXO8UHmJH+3a4D 15a7hgd6HeTT0YARWzzIhwbwZec4LZt3cSztS+YcOl6QTgfX1YFkRITIoeb0S5EZLu3T HQ== Original-Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp2120.oracle.com with ESMTP id 2r464r7xsx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 11 Mar 2019 17:48:21 +0000 Original-Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.14.4/8.14.4) with ESMTP id x2BHmLjI017731 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 11 Mar 2019 17:48:21 GMT Original-Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id x2BHmHGW030437; Mon, 11 Mar 2019 17:48:17 GMT In-Reply-To: <87wol5l6xk.fsf@web.de> X-Priority: 3 X-Mailer: Oracle Beehive Extensions for Outlook 2.0.1.9.1 (1003210) [OL 16.0.4810.0 (x86)] X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9192 signatures=668685 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1903110127 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:156241 Archived-At: > > > (1) "When using it to set a value, optional argument REMOVE non-nil > > > means to remove KEY from ALIST if the new value is `eql' to DEFAULT." > > > > > > I wonder if there are use cases where the user wants something differ= ent > > > than `eql'? E.g. `equal' when the associations are strings? Note th= at > > > this is something different than TESTFN which is for comparing keys. > > > > I think so, yes. Why wouldn't we want to allow that? >=20 > To not add one more argument? An _optional_ arg. Why wouldn't we want it? BTW, how does `alist-get' deal with a value that is a list: `(a 1)' instead of `(a . 1)'? I guess it just considers the VALUE to be `(1)'. If so, is `eql' really appropriate for most such cases (which are quite common)? And even for `(a . (1 2))', aka `(a 1 2)', is `eql' appropriate? Since the cdr of a list is more typically a list, why would we choose `eql' as the default value-comparison predicate? To compare lists the default predicate should be `equal' (or possibly but not likely `eq'), no? > If we do that, I guess I would rather allow that the non-nil value of > REMOVE is allowed to be a function. A related use case would be to > allow to delete the association of a key independently from associated > value. That'd be OK. If the second test function would be only for removal then letting REMOVE be a function would be fine. Presumably it would be a predicate, testing each full entry (the cons that holds both key and value), not just the value. > > > (2) The remove feature has a strange corner case. Normally the > > > first found association is removed, > > > > So "normally" it's really "remove one". > > > > Why is this? What's the point of REMOVE - why is > > it needed (added to the design) at all? Is it to > > provide a way to remove all entries with a given > > key or only the first such? >=20 > The first. Then why did (does?) the doc say "if the new value is `eql' to DEFAULT"? It sounds like it removes only the entries with a given key AND a given value. Anyway, if that's all REMOVE does (removes all occurrences), and if it can be a predicate, then it sounds like it just does `cl-delete-if'. If so, what's an example of why/when someone would want to use `setf' and `alist-get' to remove entries, as opposed to just using `cl-delete-if'? I may be missing something. I'm not familiar with the whole bug thread and I'm looking at the existing (old) doc string. > > If we want to provide for pretty much everything > > that one typically does with an alist (without > > `alist-get') then don't we need to provide for the > > ability to do any kind of removal - or other > > operations - on alist elements that have a given key? > > > > Should "set" and "remove" operations not (at least > > be able to) obtain the _full_ sequence (in entry > > order) of such matching elements, and then perform > > specific operations on that sequence (such as setting > > or removing the first one, the Nth one, or all of > > them)? > > > > If we were not trying to allow `alist-get' to be > > usable as a generalized variable then I suppose > > we wouldn't need to worry about any of this. >=20 > We tried. I think the result should be consistent and convenient, but > we don't need to implement all realizations of all operations for the > generalized variable. Then isn't it a bit misleading for the function name and doc to suggest that this is a general way of using alists? There is already some misunderstanding out there about alists, with some folks thinking that there should only ever be a single entry with a given key (which is true of a hash table). Won't this augment such confusion? So far, I guess I don't see the use case for making it a generalized variable. It's easy enough to set alist values, and doing so with `setf' and `alist-get' sounds more complicated, not less. For getting, I think I get it: folks apparently don't want to get the full element and then dig out the value (cdr) from it. (Is there more to it than that?) For setting and removing, I don't get the advantage, so far. > One thing I don't find consistent is the case where the alist already > has multiple occurrences of a key. E.g. >=20 > (setq my-alist '((a . 1) (b . 2) (a . -1))) > (setf (alist-get 'a my-alist 1 'remove) 1) > my-alist =3D=3D> ((b . 2) (a . -1)) >=20 > (alist-get 'a my-alist 1) > =3D=3D> -1 (!) >=20 > One would expect 1, of course. Why? The doc says that it returns DEFAULT only if KEY is not found in ALIST. But entry (a . -1) finds `a' associated with -1. What am I missing? But if you don't find it inconsistent then that's a problem, because many (most, I expect) uses of alists do have some multiple occurrences of a key. In any case, what you show is an example of why I wouldn't think that `setf' with `alist-get' is simpler. It may be less verbose sometimes, but it doesn't seem as clear. If, as the doc says, it removes only the entries with a given key AND a given value, then isn't this: (setq my-alist (cl-delete-if (lambda (entry) (and (eql (car entry 'a)) (eql (cdr entry 1)))) my-alist)) more straightforward than this: (setf (alist-get 'a my-alist 1 'remove) 1)? Or if, as I think you're saying, it removes all the entries with a given key, regardless of the values, then just this: (setq my-alist (cl-delete-if (lambda (entry) (eql (car entry 'a))) my-alist)) I find the `setf' with `remove' and double 1's to be confusing. It looks like it removes all entries for key `a' that have value 1, and then it _creates_ an entry (a . 1). I know that it doesn't do that, but to me that's what it looks like it's saying. If there really is a good use case for `alist-get' to be a generalized variable, and for that to let you remove entries and not just set/create entries, then it seems like a better syntax could be found. FWIW, to me the whole remove thing seems to fly in the face of what `alist-get' and `setf' are about. With REMOVE `setf' is NOT setting an alist element. Instead, it's changing the alist structure - it's not acting on elements of the list. `alist-get' specifies an alist entry (a single one, BTW). `setf' of `alist-get' should set/create an alist entry (a single one, BTW). Otherwise, we're abusing the intention of one or both of these "functions". No? > > It would be good to see a statement/spec of what > > `alist-get' is trying to accomplish, especially > > wrt setting, testing (diff predicates), and > > removing. >=20 > Yes, this is what my patch will try to accomplish. Great. Thx.