diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index d00281b..70e3218 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -25,10 +25,12 @@ A release with known breaking changes is marked with: === Added -* Remove use of `resolve` in ordered-set. https://github.com/clj-commons/ordered/issues/71[#71] * Added ClojureScript support for `ordered-set`: https://github.com/clj-commons/ordered/issues/66[#66] (thanks, https://github.com/marksto[@marksto]!) -* Add support for `contains?` and `find` on transient `ordered-map`, fix bug related to self-referential transient maps: https://github.com/clj-commons/ordered/issues/69[#69] +* Added `ordered-map?` and `ordered-set?` predicates: https://github.com/clj-commons/ordered/issues/102[#102] +(https://github.com/lread[@lread]) +* Add support for `contains?` and `find` on transient `ordered-map`: https://github.com/clj-commons/ordered/issues/69[#69] +(https://github.com/NoahTheDuke[@NoahTheDuke]) === Changed @@ -37,6 +39,7 @@ Because we made internals private, there is a tiny chance this release could be We found no uses of these internals in the wild. Let us know if you have been affected. https://github.com/clj-commons/ordered/issues/98[#98] +(https://github.com/lread[@lread]) ** Public API docstrings and function signatures verified and consistent across Clojure & ClojureScript *** `flatland.ordered.common` **** `compact` @@ -80,6 +83,12 @@ https://github.com/clj-commons/ordered/issues/81[#81] ** Automated release workflow https://github.com/clj-commons/ordered/pull/96[#96] (https://github.com/lread[@lread]) +=== Fixed +* Remove use of `resolve` in ordered-set. https://github.com/clj-commons/ordered/issues/71[#71] +(https://github.com/NoahTheDuke[@NoahTheDuke]) +* Fix bug related to self-referential transient maps: https://github.com/clj-commons/ordered/issues/69[#69] +(https://github.com/NoahTheDuke[@NoahTheDuke]) + == 1.15.12 - 2024-05-13 * Fix NPE when hashing ordered-set that contain `nil` diff --git a/doc/01-user-guide.adoc b/doc/01-user-guide.adoc index 7e655cf..31eef1e 100644 --- a/doc/01-user-guide.adoc +++ b/doc/01-user-guide.adoc @@ -85,6 +85,22 @@ We test on macOS, Windows, and Linux. ;; just as it would if it were never part of the set. (-> (oset/ordered-set 4 3 1 8 2) (disj 8) (conj 8)) => #ordered/set (4 3 1 2 8) + +;; You can check if you are dealing with a flatland ordered set +(oset/ordered-set? (oset/ordered-set :a :b :c)) +=> true +---- + +In Clojure, you can use https://clojure.org/reference/transients[transient] on ordered sets: + +[source,clojure] +---- +(def t (transient (oset/ordered-set))) +(oset/ordered-set? t) +=> false +(def os (persistent! t)) +(oset/ordered-set? os) +=> true ---- == Maps @@ -114,8 +130,25 @@ We test on macOS, Windows, and Linux. ;; it would if it were never part of the map. (-> (omap/ordered-map :b 2 :a 1 :d 4) (dissoc :b) (assoc :b 7)) => #ordered/map ([:a 1] [:d 4] [:b 7]) + +;; You can check if you are dealing with a flatland ordered map +(omap/ordered-map? (omap/ordered-map :a 1)) +=> true ---- +In Clojure, you can use https://clojure.org/reference/transients[transient] on ordered maps: + +[source,clojure] +---- +(def t (transient (omap/ordered-map))) +(omap/ordered-map? t) +=> false +(def om (persistent! t)) +(omap/ordered-map? om) +=> true +---- + + [#cljs] == ClojureScript @@ -147,7 +180,7 @@ To read these literals at runtime, you must register the tags: => #ordered/set (4 3 2) ---- -A few things are JVM-only: +Things are JVM Clojure only: * `transient` support * `flatland.ordered.common/compact` diff --git a/src/flatland/ordered/map.clj b/src/flatland/ordered/map.clj index 4e798ea..f8de05c 100644 --- a/src/flatland/ordered/map.clj +++ b/src/flatland/ordered/map.clj @@ -225,3 +225,8 @@ key and then later assoc'ing it puts it at the end, as if it were "Called by data_readers" [coll] `(ordered-map ~(vec coll))) + +(defn ordered-map? + "Returns `true` if `x` is a flatland ordered map. Does not include `transient` variant." + [x] + (instance? OrderedMap x)) diff --git a/src/flatland/ordered/map.cljs b/src/flatland/ordered/map.cljs index e50fa3f..c154f53 100644 --- a/src/flatland/ordered/map.cljs +++ b/src/flatland/ordered/map.cljs @@ -151,6 +151,11 @@ key and then later assoc'ing it puts it at the end, as if it were ([k v & kvs] (apply assoc empty-ordered-map k v kvs))) +(defn ordered-map? + "Returns `true` if `x` is a flatland ordered map. Does not include `transient` variant." + [x] + (instance? OrderedMap x)) + (comment (ordered-map :foo 123 :bar 456) ;; => #ordered/map [:foo 123, :bar 456] diff --git a/src/flatland/ordered/set.clj b/src/flatland/ordered/set.clj index e3b4e7b..7fa8c3e 100644 --- a/src/flatland/ordered/set.clj +++ b/src/flatland/ordered/set.clj @@ -159,3 +159,8 @@ (defmethod print-method OrderedSet [o ^Writer w] (.write w "#ordered/set ") (print-method (seq o) w)) + +(defn ordered-set? + "Returns `true` if `x` is a flatland ordered set. Does not include `transient` variant." + [x] + (instance? OrderedSet x)) diff --git a/src/flatland/ordered/set.cljs b/src/flatland/ordered/set.cljs index 90b3979..2a4f06b 100644 --- a/src/flatland/ordered/set.cljs +++ b/src/flatland/ordered/set.cljs @@ -119,3 +119,8 @@ Used for registering runtime tag parsers for ClojureScript, see [docs](/doc/01-user-guide.adoc#cljs)." [elements] (into empty-ordered-set elements)) + +(defn ordered-set? + "Returns `true` if `x` is a flatland ordered set. Does not include `transient` variant." + [x] + (instance? OrderedSet x)) diff --git a/test/flatland/ordered/map_test.cljc b/test/flatland/ordered/map_test.cljc index a1d79de..b6e08fa 100644 --- a/test/flatland/ordered/map_test.cljc +++ b/test/flatland/ordered/map_test.cljc @@ -1,7 +1,7 @@ (ns flatland.ordered.map-test (:require [clojure.test :refer [deftest testing is are]] [flatland.ordered.test-report] - [flatland.ordered.map :refer [#?(:cljs OrderedMap) ordered-map]] + [flatland.ordered.map :refer [#?(:cljs OrderedMap) ordered-map ordered-map?]] #?(:clj [flatland.ordered.common :refer [compact]] :cljs [cljs.reader :as reader])) #?(:clj (:import flatland.ordered.map.OrderedMap))) @@ -241,3 +241,18 @@ [[nil :a]] [[:a nil]] [[nil nil]]))) + +(deftest predicate-test + (is (= true (map? (ordered-map)))) + (is (= true (coll? (ordered-map)))) + (is (= true (associative? (ordered-map)))) + (is (= true (counted? (ordered-map)))) + (is (= true (ordered-map? (ordered-map)))) + (is (= true (ordered-map? (ordered-map :a 1)))) + (is (= false (ordered-map? nil))) + (is (= false (ordered-map? {:a 1})))) + +#?(:clj + (deftest predicate-transient-test + (is (= false (ordered-map? (transient (ordered-map))))) + (is (= true (ordered-map? (persistent! (transient (ordered-map)))))))) diff --git a/test/flatland/ordered/set_test.cljc b/test/flatland/ordered/set_test.cljc index 67539c8..acae057 100644 --- a/test/flatland/ordered/set_test.cljc +++ b/test/flatland/ordered/set_test.cljc @@ -4,7 +4,7 @@ [flatland.ordered.test-report] [flatland.ordered.set :refer [#?(:cljs OrderedSet) #?(:cljs into-ordered-set) - ordered-set]] + ordered-set ordered-set?]] #?(:clj [flatland.ordered.common :refer [compact]] :cljs [cljs.reader :as reader])) #?(:clj (:import (flatland.ordered.set OrderedSet)))) @@ -250,3 +250,18 @@ (are [contents] (hash-code (apply ordered-set contents)) [nil] [nil :a]))) + +(deftest predicate-test + (is (= true (set? (ordered-set)))) + (is (= true (coll? (ordered-set)))) + (is (= false (associative? (ordered-set)))) + (is (= true (counted? (ordered-set)))) + (is (= true (ordered-set? (ordered-set)))) + (is (= true (ordered-set? (ordered-set :a 1)))) + (is (= false (ordered-set? nil))) + (is (= false (ordered-set? #{:a :b})))) + +#?(:clj + (deftest predicate-transient-test + (is (= false (ordered-set? (transient (ordered-set))))) + (is (= true (ordered-set? (persistent! (transient (ordered-set))))))))