From 44c2830cfd15bff62b7a3ba74a84bf5186ac4dbe Mon Sep 17 00:00:00 2001 From: yuhan0 Date: Tue, 11 Jun 2024 07:50:18 +0800 Subject: [PATCH 1/5] Improve performance of nrepl-dict-get Avoid full traversal of dict in 2-argument call --- nrepl-dict.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nrepl-dict.el b/nrepl-dict.el index f1846d473..dadf41f7f 100644 --- a/nrepl-dict.el +++ b/nrepl-dict.el @@ -66,9 +66,12 @@ If dict is nil, return nil. If DEFAULT not provided, and KEY not in DICT, return nil. If DICT is not an nREPL dict object, an error is thrown." (when dict (if (nrepl-dict-p dict) - (if (nrepl-dict-contains dict key) - (lax-plist-get (cdr dict) key) - default) + ;; Note: The structure of the following expression avoids the + ;; expensive containment check in nearly all cases, see #3717 + (or (lax-plist-get (cdr dict) key) + (when default + (and (not (nrepl-dict-contains dict key)) + default))) (error "Not an nREPL dict object: %s" dict)))) (defun nrepl-dict-put (dict key value) From 154bd08b70dd35d5a2393fbeadaadbbabc9de945 Mon Sep 17 00:00:00 2001 From: yuhan0 Date: Tue, 11 Jun 2024 07:50:36 +0800 Subject: [PATCH 2/5] Deprecate 3-argument call to nrepl-dict-get Calling the function with 3 arguments will continue to work, but raise a warning during byte compilation. --- nrepl-dict.el | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/nrepl-dict.el b/nrepl-dict.el index dadf41f7f..a408d1362 100644 --- a/nrepl-dict.el +++ b/nrepl-dict.el @@ -61,14 +61,20 @@ whose car is KEY. Comparison is done with `equal'." (member key (nrepl-dict-keys dict))) (defun nrepl-dict-get (dict key &optional default) - "Get from DICT value associated with KEY, optional DEFAULT if KEY not in DICT. -If dict is nil, return nil. If DEFAULT not provided, and KEY not in DICT, -return nil. If DICT is not an nREPL dict object, an error is thrown." + "Get from DICT value associated with KEY. +If DICT is nil, return nil. +If DICT is not an nREPL dict object, an error is thrown. + +If KEY is not in DICT, return DEFAULT (if provided). +Note that the use of DEFAULT is deprecated and will be +removed in a future release." + (declare (advertised-calling-convention (dict key) "1.16")) (when dict (if (nrepl-dict-p dict) ;; Note: The structure of the following expression avoids the ;; expensive containment check in nearly all cases, see #3717 (or (lax-plist-get (cdr dict) key) + ;; TODO: remove DEFAULT argument and the following clause (when default (and (not (nrepl-dict-contains dict key)) default))) From ef8102db6c6cc9e978c8a46de547c6326b6c9188 Mon Sep 17 00:00:00 2001 From: yuhan0 Date: Tue, 11 Jun 2024 07:37:37 +0800 Subject: [PATCH 3/5] Add details to nrepl-dict commentary --- nrepl-dict.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nrepl-dict.el b/nrepl-dict.el index a408d1362..0b56f2ab4 100644 --- a/nrepl-dict.el +++ b/nrepl-dict.el @@ -28,7 +28,8 @@ ;;; Commentary: ;; ;; Provides functions to interact with and create `nrepl-dict's. These are -;; simply plists with an extra element at the head. +;; simply plists with an extra element at the head, and using `equal' for +;; comparison of string keys. ;;; Code: (require 'cl-lib) @@ -199,7 +200,7 @@ If NO-JOIN is given, return the first non nil dict." (t `(,dict1 ,dict2))))) -;;; Dbind +;;; Destructuring-bind of string keys (defmacro nrepl-dbind-response (response keys &rest body) "Destructure an nREPL RESPONSE dict. Bind the value of the provided KEYS and execute BODY." From f5bbc78f0e5f8368c5e5ae919b6cf53e0fd7eeee Mon Sep 17 00:00:00 2001 From: yuhan0 Date: Tue, 11 Jun 2024 07:40:48 +0800 Subject: [PATCH 4/5] Inline nrepl-dict predicates --- nrepl-dict.el | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nrepl-dict.el b/nrepl-dict.el index 0b56f2ab4..d8daeb5cf 100644 --- a/nrepl-dict.el +++ b/nrepl-dict.el @@ -45,12 +45,11 @@ (maphash (lambda (k v) (nrepl-dict-put dict k v)) hash) dict)) -(defun nrepl-dict-p (object) +(defsubst nrepl-dict-p (object) "Return t if OBJECT is an nREPL dict." - (and (listp object) - (eq (car object) 'dict))) + (eq (car-safe object) 'dict)) -(defun nrepl-dict-empty-p (dict) +(defsubst nrepl-dict-empty-p (dict) "Return t if nREPL dict DICT is empty." (null (cdr dict))) From 344005f5722f79e0a4e928a338d0afa9e8d45ac3 Mon Sep 17 00:00:00 2001 From: yuhan0 Date: Tue, 11 Jun 2024 08:05:13 +0800 Subject: [PATCH 5/5] Modify changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de93bb2b..06efd7fc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Changes - [#3714](https://github.com/clojure-emacs/cider/pull/3714): Show progress when evaluating files using `cider-load-all-files`. +- [#3713](https://github.com/clojure-emacs/cider/pull/3713): Optimize `nrepl-dict-get` and deprecate its 3-argument arity. ### Bugs fixed