forked from clojureman/special
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
916b415
commit 18ba401
Showing
2 changed files
with
122 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
(ns special.eagerize) | ||
|
||
#?(:clj | ||
(defonce array-object-type (delay (Class/forName "[Ljava.lang.Object;")))) | ||
|
||
(defprotocol Eagerizable | ||
"Container types that want to work safely with special should implement this | ||
protocol in a way where all elements they contain, even deeply nested, will | ||
be realized and made eager." | ||
(eagerize [this])) | ||
|
||
#?(:clj | ||
(extend-protocol Eagerizable | ||
nil | ||
(eagerize [this] this) | ||
java.lang.Object | ||
(eagerize [this] (if (instance? @array-object-type this) | ||
(doall (map eagerize this)) | ||
this)) | ||
clojure.lang.IPersistentList | ||
(eagerize [this] (apply list (map eagerize this))) | ||
clojure.lang.IMapEntry | ||
(eagerize [this] (vec (map eagerize this))) | ||
clojure.lang.ISeq | ||
(eagerize [this] (doall (map eagerize this))) | ||
clojure.lang.IRecord | ||
(eagerize [this] (reduce (fn [r x] (conj r (eagerize x))) this this)) | ||
clojure.lang.IPersistentCollection | ||
(eagerize [this] (into (empty this) (map eagerize this))) | ||
clojure.lang.IType | ||
(eagerize [this] (doall | ||
(map #(eagerize (.get % this)) | ||
(.getFields (class this))))) | ||
clojure.lang.Delay | ||
(eagerize [this] (eagerize (deref this))) | ||
java.lang.Iterable | ||
(eagerize [this] (doall (map eagerize this))) | ||
java.util.Map | ||
(eagerize [this] (doall (map eagerize (.values this)))))) | ||
|
||
#?(:cljs (extend-protocol Eagerizable | ||
default | ||
(eagerize [this] (pr-str this)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
(ns special.eagerize-test | ||
(:require [clojure.test :refer [deftest is testing]] | ||
[special.eagerize :refer [eagerize]])) | ||
|
||
(defn- make-nested-lazy-list | ||
"Returns a lazy-sequece of e. | ||
Defaults to random-ints when called with no args." | ||
([] | ||
(make-nested-lazy-list #(rand-int 42))) | ||
([e] | ||
(repeatedly 10 (constantly e)))) | ||
|
||
(defrecord TestRecord [s]) | ||
(deftype TestType [s]) | ||
|
||
(deftest eagerize-test | ||
(testing "Can eagerize deep nested Clojure IPersistentList." | ||
(is (realized? | ||
(let [ls (list (make-nested-lazy-list))] | ||
(eagerize ls) | ||
(first ls))))) | ||
|
||
(testing "Can eagerize deep nested Clojure IMapEntry." | ||
(is (realized? | ||
(let [ls (first {:e (make-nested-lazy-list)})] | ||
(eagerize ls) | ||
(val ls))))) | ||
|
||
(testing "Can eagerize deep nested Clojure ISeq." | ||
(is (realized? | ||
(let [ls (make-nested-lazy-list (make-nested-lazy-list))] | ||
(eagerize ls) | ||
(first ls))))) | ||
|
||
(testing "Can eagerize deep nested Clojure IRecord." | ||
(is (realized? | ||
(let [ls (->TestRecord (make-nested-lazy-list))] | ||
(eagerize ls) | ||
(:s ls))))) | ||
|
||
(testing "Can eagerize deep nested Clojure IType." | ||
(is (realized? | ||
(let [ls (TestType. (make-nested-lazy-list))] | ||
(eagerize ls) | ||
(.-s ls))))) | ||
|
||
(testing "Can eagerize deep nested Clojure Delay." | ||
(is (realized? | ||
(let [ls (delay (make-nested-lazy-list))] | ||
(eagerize ls) | ||
@ls)))) | ||
|
||
(testing "Can eagerize deep nested Java Iterable." | ||
(is (realized? | ||
(let [ls (doto (java.util.LinkedList.) | ||
(.add (make-nested-lazy-list)))] | ||
(eagerize ls) | ||
(first ls))))) | ||
|
||
(testing "Can eagerize deep nested Java AbstractMap." | ||
(is (realized? | ||
(let [ls (doto (java.util.HashMap.) | ||
(.put "a" (make-nested-lazy-list)))] | ||
(eagerize ls) | ||
(.get ls "a"))))) | ||
|
||
(testing "Can eagerize deep nested Java Stack." | ||
(is (realized? | ||
(let [ls (doto (java.util.Stack.) | ||
(.push (make-nested-lazy-list)))] | ||
(eagerize ls) | ||
(.pop ls))))) | ||
|
||
(testing "Can eagerize deep nested Java Arrays." | ||
(is (realized? | ||
(let [ls (doto (make-array clojure.lang.ISeq 2) | ||
(aset 0 (make-nested-lazy-list)))] | ||
(eagerize ls) | ||
(aget ls 0)))))) |