OSX でナニ

とりあえず github から clone して ant を。

$ git clone git://github.com/richhickey/clojure.git
$ ant
$

出力は略してます。ls してみたら clojure.jar があるんで以下。

e$ java -cp clojure.jar clojure.main
Clojure 1.2.0-master-SNAPSHOT
user=>

動くってコトで、Reference を確認しつつごにょごにょしてみる方向で。

リファレンスを

gdgd 確認中に reduce という手続きを見つけてます。Clojure special_forms の項にて以下の定義な例。

(defn
#^{:doc "mymax [xs+] gets the maximum value in xs using > "
   :test (fn []
             (assert (= 42  (mymax 2 42 5 4))))
   :user/comment "this is the best fn ever!"}
  mymax
  ([x] x)
  ([x y] (if (> x y) x y))
  ([x y & more]
   (reduce mymax (mymax x y) more)))

ええと IBM の解説によると

reduce 関数はパラメータとして関数と配列の 2 つを取り、関数を数列の最初の 2 つの要素に適用し、その結果と数列の次の要素に再び関数を適用します。


とある。これ、以下だとエラーになったので

user=> (reduce + 1 '(2 3 4) '(5 6 7))
java.lang.IllegalArgumentException: Wrong number of args passed to: core$reduce (NO_SOURCE_FILE:0)

おそらく引数は以下なカンジで定義されてるのかな。

(fn reduce 
  ([f n l] ...)
  ([f l] ...))

色々試してみたら以下なカンジ。

user=> (reduce + '(1 2 3 4) '(5 6 7))
java.lang.ClassCastException: clojure.lang.PersistentList (NO_SOURCE_FILE:0)
user=> (reduce + 1)
java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer (NO_SOURCE_FILE:0)

おそらくは値を戻す手続き呼び出しが入ることを想定してるんだろうな。

あら

でも Clojure special_forms の項の fn のサンプルコードで以下な記述があるな。

(def mult
  (fn this
      ([] 1)
      ([x] x)
      ([x y] (. clojure.lang.Numbers (multiply x y)))
      ([x y & more]
          (apply this (this x y) more))))

これ式で reduce な書き方で mymax を書いてみると以下?

(def mymax
  (fn this
    ([x] x)
    ([x y] (if (> x y) x y))
    ([x y & more]
      (reduce this (this x y) more))))

apply でも書ける、のでしょうか。

(def mymax
  (fn this
    ([x] x)
    ([x y] (if (> x y) x y))
    ([x y & more]
      (apply this (this x y) more))))

試してみたんですがどっちも動いた。ちなみに [x y & more] って書き方は Scheme の (x y . more) って書き方と等価なのに違いない、って勝手判断。