ClojureでsleepするにはJavaのThread/sleepを使えばいいわけですが、(sleep 1 :min) (sleep 2 :minute) (sleep 3 :s)などのように単位をつけてsleepできるものを作ってみます。
単位についてはある程度あいまいに指定が可能なように、前方一致していればマップから値を取得できるfuzzy-get関数も一緒に作ります。
※ついでにfuzzy-getはkeyが文字列かキーワードかシンボルか区別せずに取れるようにもしておきます。
※複数該当する場合は辞書順で早いほうとします。
fuzzy-get.clj
(defn name? [x] (or (string? x) (instance? clojure.lang.Named x)))
(defn fuzzy-get [hmap key]
(if (or (not (map? hmap)) (contains? hmap key)) (get hmap key)
(let [f #(if (name? %) (name %) (str %))
ks (sort-by f (keys hmap))]
(some #(when (.startsWith ^String (f %) (f key)) (get hmap %)) ks))))
user=> (def v {:abc 1 "aiu" 2})
user=> (fuzzy-get v 'ab)
1
user=> (fuzzy-get v :ai)
2
#脱線しますが、varやnamespaceはNamedではないようですね。
user=> (instance? clojure.lang.Named :a)
true
user=> (instance? clojure.lang.Named 'a)
true
user=> (instance? clojure.lang.Named #'instance?)
false
user=> (instance? clojure.lang.Named (the-ns 'user))
false
これでfuzzy-getができたので、次はsleepです。
sleep.clj
(def time-unit
(apply hash-map (interleave [:_milliseconds :seconds :minutes :hours :days]
(reductions * [1 1000 60 60 24]))))
(defn ^long milliseconds [^double t unit]
(long (* t (fuzzy-get time-unit unit))))
(defn sleep
([^long ms] (Thread/sleep ms))
([^double t unit] (sleep (milliseconds t unit))))
これで(sleep 3 :sec) (sleep 0.1 :m)などでsleepできるようになりました。