Skip to content

Commit 1ca9fc7

Browse files
committed
memoize-multi
1 parent 4b853af commit 1ca9fc7

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ Like multimethods but multidecorators.
5959
(assert (= [] (func ::f)))
6060
```
6161

62+
## Memoization
63+
64+
```clojure
65+
(defn -main []
66+
(alter-var-root #'func md/memoize-multi))
67+
```
68+
6269
## Development
6370

6471
```

src/darkleaf/multidecorators.cljc

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,27 @@
4141
f (method @iregistry tag initial)]
4242
(apply f obj args))))))
4343

44+
(defn memoize-multi [multi]
45+
(case (:type (multi))
46+
:memoized multi
47+
:dynamic (let [{:keys [iregistry
48+
dispatch
49+
initial]} (multi)
50+
registry @iregistry
51+
mem-method (memoize method)]
52+
(fn
53+
([] {:type :memoized
54+
:registry registry
55+
:initial initial
56+
:dispatch dispatch})
57+
([obj & args]
58+
(let [tag (apply dispatch obj args)
59+
f (mem-method registry tag initial)]
60+
(apply f obj args)))))))
61+
4462
(defn ^{:style/indent :defn} decorate [multi tag decorator]
45-
(let [state (multi)
46-
iregistry (:iregistry state)]
47-
(swap! iregistry assoc tag decorator)
48-
multi))
63+
(case (:type (multi))
64+
:dynamic (let [state (multi)
65+
iregistry (:iregistry state)]
66+
(swap! iregistry assoc tag decorator)
67+
multi)))

test/darkleaf/multidecorators_test.cljc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,21 @@
3333
(t/is (= [] (multi ::f)))
3434
(t/is (= [:a :b :c :d 's] (multi `s)))
3535
#?(:clj (t/is (= [:a :b :c :d :obj] (multi String))))))
36+
37+
(t/deftest memoization
38+
(let [multi (doto (md/multi identity (constantly []))
39+
(md/decorate ::a (fn [super obj] (conj (super obj) :a)))
40+
(md/decorate ::b (fn [super obj] (conj (super obj) :b)))
41+
(md/decorate ::c (fn [super obj] (conj (super obj) :c)))
42+
(md/decorate ::d (fn [super obj] (conj (super obj) :d)))
43+
(md/decorate `s (fn [super obj] (conj (super obj) 's)))
44+
#?(:clj (md/decorate Object (fn [super obj] (conj (super obj) :obj)))))
45+
mem-multi (md/memoize-multi multi)]
46+
(doseq [_ (range 2)]
47+
(t/is (= [:a] (mem-multi ::a)))
48+
(t/is (= [:a :b] (mem-multi ::b)))
49+
(t/is (= [:a :c] (mem-multi ::c)))
50+
(t/is (= [:a :b :c :d] (mem-multi ::d)))
51+
(t/is (= [] (mem-multi ::f)))
52+
(t/is (= [:a :b :c :d 's] (mem-multi `s)))
53+
#?(:clj (t/is (= [:a :b :c :d :obj] (mem-multi String)))))))

0 commit comments

Comments
 (0)