SICPの演習をClojureでやってみた。その1
入門してはフェードアウトしているClojure。
SICP本を手に入れたので、何度目かのClojure入門をしてみましました。
環境は、repl.it の Clojure 1.8.0 です。
問題 1.3
3つの数を引数としてとり、大きい2つの数の二乗の和を返す手続きを定義せよ。
(defn sum-of-squares [a b c]
(let [[x y] (reverse (sort [a b c]))]
(+ (* x x) (* y y))))
(sum-of-squares 3 1 2)
=> 13
(defn sum-of-squares2 [a b c]
(->> [a b c]
sort
(drop 1)
(map #(* % %))
(reduce +)))
(sum-of-squares2 3 1 2)
=> 13
後者のほうが、Clojureぽいのかな?
問題 1.4
われわれの評価モデルは、演算子が合成式である組み合わせでもつかえることを観察せよ。
(def a-plus-abs-b [a b]
((if (> b 0) + -) a b)))
(a-plus-abs-b 1 2)
=> 3
(a-plus-abs-b 1 -2)
=> 3
「+」も「ー」も関数なので、これができてあたりまえなんだけど、違和感あります。
問題 1.5
Benは、彼の対面している解釈系が、作用的順序の評価を使っているか、正規順序の評価を使っているか決定するテストを発明した。次の2つの手続きを定義した。
それぞれどのような振る舞いをするか?
(defn p []
(p))
(defn test [x y]
(if (= x 0)
0
y))
(test 0 (p))
「完全に展開し、簡約する」のが、正規順序の評価。
「引数を評価し、作用させる」のが、作用的順序の評価。
(p)を評価すると、無限に再帰する。
(if)は、特殊形式?短絡評価?だから、xが0のとき、yは評価されない。
作用的順序の評価だと、(test 0 (p))の時点で、無限再帰になる。
正規順序の評価だと、(p)は評価されないので、0が返ってくる。
Clojureで試すと、「StackOverflowError」が発生。無限シーケンスが使えるので「Clojureは、遅延評価」だと勘違いしていた。作用的順序の評価で、遅延シーケンスを使うときだけ評価が遅延されているということ?
repl.it の Scheme(BiwaScheme 0.6.4) で実行してみたら、無反応になりました。こちらも、作用的順序の評価のよう。
↓要調査
ディスカッション
コメント一覧
まだ、コメントがありません