summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--autoload.c2
-rw-r--r--stdlib/place.tl7
-rw-r--r--txr.148
3 files changed, 56 insertions, 1 deletions
diff --git a/autoload.c b/autoload.c
index fcc5e014..fef8ab0d 100644
--- a/autoload.c
+++ b/autoload.c
@@ -105,7 +105,7 @@ static val place_set_entries(val fun)
lit("push"), lit("pop"), lit("swap"), lit("shift"), lit("rotate"),
lit("test-set"), lit("test-clear"), lit("compare-swap"),
lit("test-inc"), lit("test-dec"),
- lit("pushnew"), lit("del"), lit("lset"), lit("upd"),
+ lit("pushnew"), lit("del"), lit("lset"), lit("upd"), lit("ensure"),
lit("defplace"), lit("define-place-macro"), lit("define-modify-macro"),
lit("placelet"), lit("placelet*"), lit("read-once"),
lit("define-accessor"), lit("with-slots"),
diff --git a/stdlib/place.tl b/stdlib/place.tl
index 5d601834..fba9a8d6 100644
--- a/stdlib/place.tl
+++ b/stdlib/place.tl
@@ -374,6 +374,13 @@
^(placelet ((,pl ,place))
(set ,pl (call (opip ,*opip-args) ,pl)))))
+(defmacro ensure (:env env place init-expr)
+ (with-gensyms (existing)
+ (with-update-expander (getter setter) place env
+ ^(iflet ((,existing (,getter)))
+ ,existing
+ (,setter ,init-expr)))))
+
(defmacro defplace (place-destructuring-args body-sym
(getter-sym setter-sym update-body) :
((ssetter-sym clobber-body))
diff --git a/txr.1 b/txr.1
index dde521b6..5bf7b6a8 100644
--- a/txr.1
+++ b/txr.1
@@ -14384,6 +14384,19 @@ value into
and returns
.codn t .
+.meIP (ensure < place << init-expr )
+If the place is
+.codn nil ,
+evaluates
+.codn init-expr ,
+stores that value into
+.meta place
+and returns it.
+Otherwise, returns the value of
+.meta place
+without changing its value or evaluating
+.codn init-expr .
+
.meIP (inc < place <> [ delta ])
Increments
.meta place
@@ -42858,6 +42871,41 @@ expression, stores the resulting value into
and returns
.codn t .
+.coNP Macro @ ensure
+.synb
+.mets (ensure < place << init-expr )
+.syne
+.desc
+The
+.code ensure
+macro examines the value of
+.metn place .
+
+If the current value is
+.codn nil ,
+then
+.meta init-expr
+is evaluated. The value is stored in
+.meta place
+and becomes the result of the
+.code ensure
+form.
+
+If the value of
+.meta place
+is other than
+.codn nil ,
+then the form yields that value.
+In this case,
+.meta init-expr
+isn't evaluated, and
+.meta place
+isn't modified.
+
+The
+.meta place
+expression is evaluated only once to determine the place.
+
.coNP Macros @ inc and @ dec
.synb
.mets (inc < place <> [ delta ])