From 617b656d03a01003cec68164eda5720666b212f5 Mon Sep 17 00:00:00 2001 From: Shaun Williams Date: Tue, 4 Aug 2026 16:36:45 -0500 Subject: [PATCH] add volatile --- src/cljc/schema/core.cljc | 25 ++++++++++++++++++++++++- test/cljc/schema/core_test.cljc | 9 +++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/cljc/schema/core.cljc b/src/cljc/schema/core.cljc index 75d8fd1d..a7277b7d 100644 --- a/src/cljc/schema/core.cljc +++ b/src/cljc/schema/core.cljc @@ -75,7 +75,8 @@ See the docstrings of defrecord, fn, and defn for more details about how to use these macros." ;; don't exclude def because it's not a var. - (:refer-clojure :exclude [Keyword Symbol Inst atom defprotocol defrecord defn letfn defmethod fn MapEntry ->MapEntry]) + (:refer-clojure :exclude [Keyword Symbol Inst atom defprotocol defrecord defn letfn defmethod fn MapEntry ->MapEntry + volatile volatile? Volatile ->Volatile]) (:require #?(:clj [clojure.pprint :as pprint]) [clojure.string :as str] @@ -699,6 +700,28 @@ [schema] (->Atomic schema)) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Volatile schema + +(defn- volatile? [x] + #?(:clj (instance? clojure.lang.Volatile x) + :cljs (satisfies? IVolatile x))) + +(macros/defrecord-schema Volatile [schema] + Schema + (spec [this] + (collection/collection-spec + (spec/simple-precondition this volatile?) + clojure.core/volatile! + [(collection/one-element true schema (clojure.core/fn [item-fn coll] (item-fn @coll) nil))] + (clojure.core/fn [_ xs _] (clojure.core/volatile! (first xs))))) + (explain [this] (list 'volatile (explain schema)))) + +(clojure.core/defn volatile + "A volatile containing a value matching 'schema'." + [schema] + (->Volatile schema)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Map Schemas diff --git a/test/cljc/schema/core_test.cljc b/test/cljc/schema/core_test.cljc index 7b12ed2c..3bafe2b1 100644 --- a/test/cljc/schema/core_test.cljc +++ b/test/cljc/schema/core_test.cljc @@ -436,6 +436,15 @@ (invalid! s (delay "asdf") "(not (atom? a-clojure.lang.Delay))") (invalid! s (atom 1)))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Atom schemas + +(deftest volatile-test + (let [s (s/volatile s/Str)] + (is (not (s/check s (volatile! "asdf")))) ;; don't expect identity after walking + (invalid! s (delay "asdf") "(not (volatile? a-clojure.lang.Delay))") + (invalid! s (volatile! 1)))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Map Schemas