emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/compat edfad44bfb: compat-29: Add with-memoization


From: ELPA Syncer
Subject: [elpa] externals/compat edfad44bfb: compat-29: Add with-memoization
Date: Tue, 10 Jan 2023 04:57:26 -0500 (EST)

branch: externals/compat
commit edfad44bfb382b3f464e27dd6ae72cbbd7793618
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>

    compat-29: Add with-memoization
---
 NEWS.org        |  1 +
 compat-29.el    | 12 ++++++++++++
 compat-tests.el | 27 +++++++++++++++++++++++++++
 compat.texi     |  7 +++++++
 4 files changed, 47 insertions(+)

diff --git a/NEWS.org b/NEWS.org
index 4c9b6019ee..968b938364 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -6,6 +6,7 @@
 - compat-25: Improve algorithmic complexity of ~sort~.
 - compat-28: Add ~make-separator-line~.
 - compat-29: Minor fixes to ~keymap-*~ functions.
+- compat-29: Add ~with-memoization~.
 
 * Release of "Compat" Version 29.1.1.0
 
diff --git a/compat-29.el b/compat-29.el
index abb9346530..6250a896e5 100644
--- a/compat-29.el
+++ b/compat-29.el
@@ -177,6 +177,18 @@ This function does not move point.  Also see 
`line-end-position'."
 
 ;;;; Defined in subr.el
 
+(compat-defmacro with-memoization (place &rest code) ;; <OK>
+  "Return the value of CODE and stash it in PLACE.
+If PLACE's value is non-nil, then don't bother evaluating CODE
+and return the value found in PLACE instead."
+  (declare (indent 1))
+  (gv-letplace (getter setter) place
+    `(or ,getter
+         ,(macroexp-let2 nil val (macroexp-progn code)
+            `(progn
+               ,(funcall setter val)
+               ,val)))))
+
 (compat-defalias string-split split-string) ;; <OK>
 
 (compat-defun function-alias-p (func &optional noerror) ;; <OK>
diff --git a/compat-tests.el b/compat-tests.el
index c1a812cad8..5eea987985 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -60,6 +60,33 @@
     (setq list (funcall sym list "first" 1 #'string=))
     (should (eq (compat-call plist-get list "first" #'string=) 1))))
 
+(ert-deftest with-memoization ()
+  (let ((x (cons nil nil)) y computed)
+    (with-memoization (car x)
+      (setq computed 'a))
+    (should-equal (car x) 'a)
+    (should-equal computed 'a)
+    (with-memoization (car x)
+      (setq computed 'b))
+    (should-equal (car x) 'a)
+    (should-equal computed 'a)
+    (with-memoization (cdr x)
+      (setq computed 'c))
+    (should-equal (cdr x) 'c)
+    (should-equal computed 'c)
+    (with-memoization (cdr x)
+      (setq computed 'd))
+    (should-equal (cdr x) 'c)
+    (should-equal computed 'c)
+    (with-memoization y
+      (setq computed 'e))
+    (should-equal y 'e)
+    (should-equal computed 'e)
+    (with-memoization y
+      (setq computed 'f))
+    (should-equal y 'e)
+    (should-equal computed 'e)))
+
 (ert-deftest make-separator-line ()
   (should-equal (length (make-separator-line 10)) 11)
   (should (string-suffix-p "\n" (make-separator-line 10)))
diff --git a/compat.texi b/compat.texi
index 6d3a45e105..a08d05d19e 100644
--- a/compat.texi
+++ b/compat.texi
@@ -2022,6 +2022,13 @@ provided by Compat. Note that due to upstream changes, 
it might happen
 that there will be the need for changes, so use these functions with
 care.
 
+@c copied from lispref/cl.texi
+@defmac with-memoization @var{place} @var{code}@dots{}
+This macro provides a simple way to do memoization.  @var{code} is
+evaluated and then stashed in @var{place}.  If @var{place}'s value is
+non-@code{nil}, return that value instead of evaluating @var{code}.
+@end defmac
+
 @c copied from lispref/positions.texi
 @defun pos-bol &optional count
 Like @code{line-beginning-position}, but ignores fields (and is more



reply via email to

[Prev in Thread] Current Thread [Next in Thread]