Code Aquarium

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

clojure.inspectorをちょっとだけ見やすく

(require '[clojure.inspector :as insp])
(import 'java.awt.Font)

(defn find-children
  [^java.awt.Component co ^Class cls]
  (some->> co .getComponents
           (filter #(instance? cls %))))

(defn custom-inspect-tree
  [data]
  (let [font (Font. "VL Gothic" Font/PLAIN 20)
        frame (doto (insp/inspect-tree data)
                (.setVisible false))
        jtree (-> frame .getContentPane
                  (find-children javax.swing.JScrollPane) first
                  (find-children javax.swing.JViewport) first
                  (find-children javax.swing.JTree) first)]
    (some-> jtree (.setFont font))
    (doto frame
      (.setSize 1000 800)
      (.setVisible true))))

clojure.inspector は出力が swing の JFrame 固定なのではっきり言って使い勝手が悪いモジュールです。しかもLinuxやWindowsだとフォントが小さいため、目の悪い私にはちょっとした確認で使うにもつらい代物です。
せめてもう少しフォントサイズが大きければなーと思って、こんなの書いて見ました。find-children は jQueryインスパイアだったりします。

(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が来たため、マクロ展開後のコードが前より読みやすくなりました。