Skip to content

Commit

Permalink
Merge upstream PR clojureman#9
Browse files Browse the repository at this point in the history
  • Loading branch information
damienstanton committed Jul 29, 2023
1 parent 916b415 commit 18ba401
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/special/eagerize.cljc
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))))
79 changes: 79 additions & 0 deletions test/special/eagerize_test.clj
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))))))

0 comments on commit 18ba401

Please sign in to comment.