ロケット打ち上げClojure版

Clojureでも書いてみた。(C#版はこちら)
この2週間ほどで自分のコーディングスタイルもだいぶ変わったなぁ。今の自分なりの「Clojureらしいプログラム」はこんな感じ。

(use '[clojure.contrib.pprint :only (cl-format)])

(def fmt (partial cl-format false))

(defn rocket [id cnt]
  (let [cnt (dec cnt)]
    (->> (range cnt 0 -1)
	 (map (partial fmt "[No.~a ~a]" id))
	 (#(lazy-cat
	    %
	    [(fmt "[~a番ロケット発射!]" id)]
	    (repeat (fmt "[~a番ロケットは既に発射されました]" id))))
	 (map list (iterate dec cnt)))))

(defn launch [task & rockets]
  (letfn [(merge- [& args]
		  (list
		   (->> args (map first) (every? neg?))
		   (->> args (map second) (apply str))))]
	 (->> (apply map merge- rockets)
	      (take-while (complement first))
	      (map second)
	      (map task))))

(defn main []
  (launch println
	  (rocket 1 3)
	  (rocket 2 7)
	  (rocket 3 5)))

(dorun (main))

破壊的操作は一切なし(多分)。

  • >> の便利さに完全にはまってます。左から右、上から下へ流れて行く感じには従来のLispにない気持ちよさがありますね。

シーケンスと高階関数でロジックを組みたたていくやり方も新鮮で楽しいです。こういう書き方ができるのはコアに根ざした遅延シーケンスの存在が大きいと思います。
mapを多用してしまうのがちょっと気になりますが。


どうもこの記事の元ネタにしたコードはこの人のみたいだな。ぐぐったら出てきた。「Lisp(scheme) のどこがうれしいの?」