Arantium Maestum

プログラミング、囲碁、読書の話題

SICPの勉強 問題2.2

線のデータを定義。

(defn make-segment [start-point end-point]
  [start-point end-point])

(defn start-segment [segment]
  (first segment))

(defn end-segment [segment]
  (last segment))

その前提となる点のデータを定義。

(defn make-point [x y]
  [x y])

(defn x-point [point]
  (first point))

(defn y-point [point]
  (last point))

点と線を踏まえて、線の真ん中にくる点を求める関数:

(defn average [x y]
  (/ (+ x y) 2))

(defn mid-point [segment]
  (let [start (start-segment segment)
        end   (end-segment segment)]
    [(average (x-point start) (x-point end))
     (average (y-point start) (y-point end))]))

(defn print-point [point]
  (println 
    (str "("
         (x-point point)
         ", "
         (y-point point)
         ")")))

使ってみる:

(def a 
  (make-segment 
    (make-point 10 10) 
    (make-segment 16 12)))

(print-point (mid-point a))

線も点もただのベクトルなわけだが、そこでfirstとかlastとかを直接使いたい気持ちをぐっとこらえる、というのがポイント。

しかし、carとかcdrとかだったら、それはまあ当然より意味のある関数名にラップしたくなるのも当然である。というか何だこの関数名、といつも思っていた。

今ぱっとググったらContents of Address RegisterとContents of Decrement Registerの意らしい。基本的に昔のlispは言語の基本操作に分かりやすい名前をつけるということを非常に軽視していたように(今からすると)感じてしまう。Lispのような高級言語でいきなりレジスタの話が出るのは抽象性のレベルがおかしいのではないか?