|
| 1 | +; The MIT License (MIT) |
| 2 | +; |
| 3 | +; Copyright (c) 2013 Zachary Tellman |
| 4 | +; |
| 5 | +; Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | +; of this software and associated documentation files (the "Software"), to deal |
| 7 | +; in the Software without restriction, including without limitation the rights |
| 8 | +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 9 | +; copies of the Software, and to permit persons to whom the Software is |
| 10 | +; furnished to do so, subject to the following conditions: |
| 11 | +; |
| 12 | +; The above copyright notice and this permission notice shall be included in |
| 13 | +; all copies or substantial portions of the Software.) |
| 14 | +; |
| 15 | +; Partly Copied from https://github.com/ztellman/potemkin/blob/master/src/potemkin/util.clj |
| 16 | +; to avoid having a dependency |
| 17 | +(ns java-time.potemkin.util |
| 18 | + (:import [java.util.concurrent ConcurrentHashMap])) |
| 19 | + |
| 20 | +;;; fast-memoize |
| 21 | + |
| 22 | +(definline re-nil [x] |
| 23 | + `(let [x# ~x] |
| 24 | + (if (identical? ::nil x#) nil x#))) |
| 25 | + |
| 26 | +(definline de-nil [x] |
| 27 | + `(let [x# ~x] |
| 28 | + (if (nil? x#) ::nil x#))) |
| 29 | + |
| 30 | +(defmacro memoize-form [m f & args] |
| 31 | + `(let [k# (vector ~@args)] |
| 32 | + (let [v# (.get ~m k#)] |
| 33 | + (if-not (nil? v#) |
| 34 | + (re-nil v#) |
| 35 | + (let [v# (de-nil (~f ~@args))] |
| 36 | + (re-nil (or (.putIfAbsent ~m k# v#) v#))))))) |
| 37 | + |
| 38 | +(defn fast-memoize |
| 39 | + "A version of `memoize` which has equivalent behavior, but is faster." |
| 40 | + [f] |
| 41 | + (let [m (ConcurrentHashMap.)] |
| 42 | + (fn |
| 43 | + ([] |
| 44 | + (memoize-form m f)) |
| 45 | + ([x] |
| 46 | + (memoize-form m f x)) |
| 47 | + ([x y] |
| 48 | + (memoize-form m f x y)) |
| 49 | + ([x y z] |
| 50 | + (memoize-form m f x y z)) |
| 51 | + ([x y z w] |
| 52 | + (memoize-form m f x y z w)) |
| 53 | + ([x y z w u] |
| 54 | + (memoize-form m f x y z w u)) |
| 55 | + ([x y z w u v] |
| 56 | + (memoize-form m f x y z w u v)) |
| 57 | + ([x y z w u v & rest] |
| 58 | + (let [k (list* x y z w u v rest)] |
| 59 | + (let [v (.get ^ConcurrentHashMap m k)] |
| 60 | + (if-not (nil? v) |
| 61 | + (re-nil v) |
| 62 | + (let [v (de-nil (apply f k))] |
| 63 | + (or (.putIfAbsent m k v) v))))))))) |
| 64 | + |
| 65 | +(defmacro doit |
| 66 | + "A version of doseq that doesn't emit all that inline-destroying chunked-seq code." |
| 67 | + [[x it] & body] |
| 68 | + (let [it-sym (gensym "iterable")] |
| 69 | + `(let [~it-sym ~it |
| 70 | + it# (.iterator ~(with-meta it-sym {:tag "Iterable"}))] |
| 71 | + (loop [] |
| 72 | + (when (.hasNext it#) |
| 73 | + (let [~x (.next it#)] |
| 74 | + ~@body) |
| 75 | + (recur)))))) |
0 commit comments