diff options
author | Basil L. Contovounesios <contovob@tcd.ie> | 2022-08-20 16:32:33 +0300 |
---|---|---|
committer | Basil L. Contovounesios <contovob@tcd.ie> | 2022-10-22 19:33:12 +0300 |
commit | 9da2efb670574b473ab864ae0456b4f1b38e680b (patch) | |
tree | 7d3b09fe60c368cc6c05bf46afc4d1fb4f189fa5 /src/fns.c | |
parent | f85bdb49923a60d3d0cc3bf66ad884555d92840c (diff) | |
download | emacs-9da2efb670574b473ab864ae0456b4f1b38e680b.tar.gz |
Audit some plist uses with new predicate argument
* doc/lispref/lists.texi (Plist Access): Improve description of
default predicate.
* lisp/emacs-lisp/cl-extra.el (cl-getf, cl--set-getf): Assume
plist-member always returns a cons.
* lisp/emacs-lisp/gv.el (plist-get): Support new optional predicate
argument (bug#47425#91).
* lisp/emacs-lisp/map.el: Bump minor version.
(map--dispatch): Remove now that bug#58563 is fixed. Break two
remaining uses out into corresponding cl-defmethods.
(map--plist-p): Add docstring.
(map--plist-has-predicate, map--plist-member-1, map--plist-member)
(map--plist-put-1, map--plist-put): New definitions for supporting
predicate argument backward compatibly.
(map-elt): Fix generalized variable getter under a
predicate (bug#58531). Use predicate when given a plist.
(map-put): Avoid gratuitous warnings when called without the hidden
predicate argument. Improve obsoletion message.
(map-put!): Use predicate when given a plist.
(map-contains-key): Ditto. Declare forgotten
advertised-calling-convention (bug#58531#19).
(map--put): Group definition in file together with that of map-put!.
* lisp/files-x.el (connection-local-normalize-criteria): Simplify
using mapcan + plist-get.
* lisp/net/eudc.el (eudc--plist-member): New convenience function.
(eudc-plist-member, eudc-plist-get, eudc-lax-plist-get): Use it
instead of open-coding plist-member.
* src/fns.c (Fplist_get, plist_get, Fplist_put, plist_put): Pass the
plist element as the first argument to the predicate, for
consistency with assoc + alist-get.
(Fplist_member, plist_member): Move from widget to plist section.
Open-code the EQ case in plist_member, and call it from
Fplist_member in that case, rather than the other way around.
* test/lisp/apropos-tests.el (apropos-tests-format-plist): Avoid
polluting obarray.
* test/lisp/emacs-lisp/cl-extra-tests.el (cl-getf): Extend test with
generalized variables, degenerate plists, and improper lists.
* test/lisp/emacs-lisp/gv-tests.el: Byte-compile file; in the
meantime bug#24402 seems to have been fixed or worked around.
(gv-setter-edebug): Inhibit printing messages.
(gv-plist-get): Avoid modifying constant literals. Also test with a
predicate argument.
* test/lisp/emacs-lisp/map-tests.el (with-maps-do): Simplify
docstring.
(test-map-elt-testfn): Rename...
(test-map-elt-testfn-alist): ...to this. Also test with a predicate
argument.
(test-map-elt-testfn-plist, test-map-elt-gv, test-map-elt-signature)
(test-map-put!-plist, test-map-put!-signature)
(test-map-contains-key-signature, test-map-plist-member)
(test-map-plist-put): New tests.
(test-map-contains-key-testfn): Also test with a predicate argument.
(test-map-setf-alist-overwrite-key, test-map-setf-plist-insert-key)
(test-map-setf-plist-overwrite-key): Avoid modifying constant
literals.
(test-hash-table-setf-insert-key)
(test-hash-table-setf-overwrite-key): Fix indentation.
(test-setf-map-with-function): Make test more precise.
* test/lisp/net/eudc-tests.el: New file.
* test/lisp/subr-tests.el (test-plistp): Extend test with circular
list.
* test/src/fns-tests.el (test-cycle-equal, test-cycle-nconc): Move
from plist section to circular list section.
(plist-put/odd-number-of-elements): Avoid modifying constant
literals.
(plist-member/improper-list): Simplify.
(test-plist): Move to plist section. Also test with a predicate
argument.
Diffstat (limited to 'src/fns.c')
-rw-r--r-- | src/fns.c | 97 |
1 files changed, 53 insertions, 44 deletions
diff --git a/src/fns.c b/src/fns.c index 40557923827..940fb680fc3 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2473,15 +2473,15 @@ with PROP is done using PREDICATE, which defaults to `eq'. This function doesn't signal an error if PLIST is invalid. */) (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate) { - Lisp_Object tail = plist; if (NILP (predicate)) return plist_get (plist, prop); + Lisp_Object tail = plist; FOR_EACH_TAIL_SAFE (tail) { if (! CONSP (XCDR (tail))) break; - if (!NILP (call2 (predicate, prop, XCAR (tail)))) + if (!NILP (call2 (predicate, XCAR (tail), prop))) return XCAR (XCDR (tail)); tail = XCDR (tail); } @@ -2489,7 +2489,7 @@ This function doesn't signal an error if PLIST is invalid. */) return Qnil; } -/* Faster version of the above that works with EQ only */ +/* Faster version of Fplist_get that works with EQ only. */ Lisp_Object plist_get (Lisp_Object plist, Lisp_Object prop) { @@ -2498,7 +2498,7 @@ plist_get (Lisp_Object plist, Lisp_Object prop) { if (! CONSP (XCDR (tail))) break; - if (EQ (prop, XCAR (tail))) + if (EQ (XCAR (tail), prop)) return XCAR (XCDR (tail)); tail = XCDR (tail); } @@ -2532,15 +2532,15 @@ use `(setq x (plist-put x prop val))' to be sure to use the new value. The PLIST is modified by side effects. */) (Lisp_Object plist, Lisp_Object prop, Lisp_Object val, Lisp_Object predicate) { - Lisp_Object prev = Qnil, tail = plist; if (NILP (predicate)) return plist_put (plist, prop, val); + Lisp_Object prev = Qnil, tail = plist; FOR_EACH_TAIL (tail) { if (! CONSP (XCDR (tail))) break; - if (!NILP (call2 (predicate, prop, XCAR (tail)))) + if (!NILP (call2 (predicate, XCAR (tail), prop))) { Fsetcar (XCDR (tail), val); return plist; @@ -2558,6 +2558,7 @@ The PLIST is modified by side effects. */) return plist; } +/* Faster version of Fplist_put that works with EQ only. */ Lisp_Object plist_put (Lisp_Object plist, Lisp_Object prop, Lisp_Object val) { @@ -2567,7 +2568,7 @@ plist_put (Lisp_Object plist, Lisp_Object prop, Lisp_Object val) if (! CONSP (XCDR (tail))) break; - if (EQ (prop, XCAR (tail))) + if (EQ (XCAR (tail), prop)) { Fsetcar (XCDR (tail), val); return plist; @@ -2595,6 +2596,51 @@ It can be retrieved with `(get SYMBOL PROPNAME)'. */) (symbol, plist_put (XSYMBOL (symbol)->u.s.plist, propname, value)); return value; } + +DEFUN ("plist-member", Fplist_member, Splist_member, 2, 3, 0, + doc: /* Return non-nil if PLIST has the property PROP. +PLIST is a property list, which is a list of the form +\(PROP1 VALUE1 PROP2 VALUE2 ...). + +The comparison with PROP is done using PREDICATE, which defaults to +`eq'. + +Unlike `plist-get', this allows you to distinguish between a missing +property and a property with the value nil. +The value is actually the tail of PLIST whose car is PROP. */) + (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate) +{ + if (NILP (predicate)) + return plist_member (plist, prop); + Lisp_Object tail = plist; + FOR_EACH_TAIL (tail) + { + if (!NILP (call2 (predicate, XCAR (tail), prop))) + return tail; + tail = XCDR (tail); + if (! CONSP (tail)) + break; + } + CHECK_TYPE (NILP (tail), Qplistp, plist); + return Qnil; +} + +/* Faster version of Fplist_member that works with EQ only. */ +Lisp_Object +plist_member (Lisp_Object plist, Lisp_Object prop) +{ + Lisp_Object tail = plist; + FOR_EACH_TAIL (tail) + { + if (EQ (XCAR (tail), prop)) + return tail; + tail = XCDR (tail); + if (! CONSP (tail)) + break; + } + CHECK_TYPE (NILP (tail), Qplistp, plist); + return Qnil; +} DEFUN ("eql", Feql, Seql, 2, 2, 0, doc: /* Return t if the two args are `eq' or are indistinguishable numbers. @@ -3388,43 +3434,6 @@ FILENAME are suppressed. */) bottleneck of Widget operation. Here is their translation to C, for the sole reason of efficiency. */ -DEFUN ("plist-member", Fplist_member, Splist_member, 2, 3, 0, - doc: /* Return non-nil if PLIST has the property PROP. -PLIST is a property list, which is a list of the form -\(PROP1 VALUE1 PROP2 VALUE2 ...). - -The comparison with PROP is done using PREDICATE, which defaults to -`eq'. - -Unlike `plist-get', this allows you to distinguish between a missing -property and a property with the value nil. -The value is actually the tail of PLIST whose car is PROP. */) - (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate) -{ - Lisp_Object tail = plist; - if (NILP (predicate)) - predicate = Qeq; - FOR_EACH_TAIL (tail) - { - if (!NILP (call2 (predicate, XCAR (tail), prop))) - return tail; - tail = XCDR (tail); - if (! CONSP (tail)) - break; - } - CHECK_TYPE (NILP (tail), Qplistp, plist); - return Qnil; -} - -/* plist_member isn't used much in the Emacs sources, so just provide - a shim so that the function name follows the same pattern as - plist_get/plist_put. */ -Lisp_Object -plist_member (Lisp_Object plist, Lisp_Object prop) -{ - return Fplist_member (plist, prop, Qnil); -} - DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0, doc: /* In WIDGET, set PROPERTY to VALUE. The value can later be retrieved with `widget-get'. */) |