プログラミングClojureを読んでみた。これは良い

JVM上で動く言語にはいろいろと興味があって、覚えたり QuickReflector 上に載せてみたりといろいろやっていたのは過去の話。

他のことで忙しくなってしまって熱も冷めてしまったのですが、Clojure は気になっていたので日本語訳が出たと聞き早速購入して読んでみました。

まずは、とりあえず、Java と簡単に繋ぐことができて嬉しい。
部分文字列の検索などは以下のような感じで済みます。

 (.indexOf "abcdefgabcdefg" "cd" )

これだけなら特に言うこともなし。でも、これが部分リストの検索ということになるとちょっと面倒で、見た限りでは見つけられなかったので自分で書いてみました。

(defn indexof
  "Returns position of subcoll in coll. if specified all option, returns list of all positions."
  [coll subcoll & all]
  (let [sub (seq subcoll)
        length (count sub)
        func (fn [coll subcoll from all]
          (let [parts (map vector (iterate inc 0) (partition length 1 (drop from coll)))
                result (map #(+ from %) (for [[idx elm] parts :when (= elm sub)] idx))]
            (if all result (first result))))
        head (first all)]
    (cond
      (nil? head) (func coll subcoll 0 false)
      (= (count all) 1)
        (if (keyword? head)
          (func coll subcoll 0 true)
          (func coll subcoll head false))
      :else
        (func coll subcoll head (first (next all)))
    )))

(defn subcoll?
  "Returns whether subcoll contained in coll."
  [coll subcoll]
  (not (nil? (indexof coll subcoll))))

呼び出すときは以下のような感じで。

(indexof "abcdefgabcdefg" "cd")
(indexof "abcdefgabcdefg" "cd" :all)
(indexof "abcdefgabcdefg" "cd" 4 :all)

とはいえ再帰の最適化の話がまだよくわかってなくて、:all をつけると

 (indexof (range 1 20000) '(2000 2001) :all)

なんかが落ちてしまうわけですが。

それはともかく、SISC で頑張ってみたけどすでに忘れてしまった身としてはこれから楽しみが一つできた気分です。