Code Aquarium

minazoko's blog -*- 水底のブログ -*-

(Clojure)短絡評価なsome->マクロ

ぼくのかんがえたスレッディングマクロその2
評価がnilになったら即抜けるsome->とsome->>

(ns cool-macros
  (:refer-clojure :exclude [some-> some->>]))

(defmacro ^:private
  some->* [form & exprs]
  (let [[e-first & exprs] exprs
        [e-last & exprs] (reverse exprs)]
    (if (nil? e-last)
      e-first
      (let [g (gensym)]
        `(let [~g ~e-first]
           ~(reduce (fn [acc e] `(if (nil? ~g) nil (let [~g (~form ~g ~e)] ~acc)))
                    `(if (nil? ~g) nil (~form ~g ~e-last))
                    exprs))))))

(defmacro some-> [& exprs]
  `(some->* clojure.core/-> ~@exprs))

(defmacro some->> [& exprs]
  `(some->* clojure.core/->> ~@exprs))

もうすこし綺麗にかけないかな~?

訂正

一晩眠って見直したらミスっていることに気づいたので、コード修正しました。
修正前は偽値がnilしかないことを前提にしたコードでしたが、Clojureにはfalseもあるので停止判定に nil? を使うように変更。そして判定の論理が反転したのでthenとelseの式を入れ替えました。
結果としてthen部にnilが来たため、マクロ展開後のコードが前より読みやすくなりました。