ななつめ

プロトコルを使ったレコードの練習(Clojure)

『プログラミング Clojure 第2版』p.154 にレコードについての説明がある。
ここでは、Midiシンセサイザを使って音符を例にとってレコード型を説明している。

ここで、自分のための練習として、図形を例にレコードについて勉強することにする。

長方形をレコード型として記述すると以下のようになる。

user=> (defrecord Rect [sideA sideB])
user.Rect

このレコードを使ってひとつの長方形(rect1)を作る。

user=> (def rect1 (->Rect 3 4))
#'user/rect1

この rect1 を repl に尋ねてみると、

user=> rect1
#user.Rect{:sideA 3, :sideB 4}

このように、マップの形式で表示される。

レコードはクラスなので、フィールドを以下のように表示できる。

user=> (.sideA rect1)
3

また、レコードはマップとしての性質ももつので、以下のようにも指定できる。

user=> (:sideB rect1)
4

プロトコルを使ったレコードの練習

Shape というプロトコルを定義してみる。
このプロトコルは、area という面積を求めるメソッドと、
circumference という周を求めるメソッドをもつことにする。

(defprotocol Shape
  (area [this] "The area of the shape")
  (circumference [this] "The circumference of the shape"))

プロトコルはインターフェースと同じで、メソッドの宣言だけである。

さて、このプロトコルを 長方形をあらわすレコード Rect に実装する。

;; 長方形
(defrecord Rect [x y]
  Shape
  (area [this] (* x y))
  (circumference [this] (* (+ x y) 2)))

また、円をあらわすレコード circle を作り、それに実装してみる。

;; 円
(defrecord Circle [radius]
  Shape
  (area [this]
    (let [PI 3.14]
      (* radius radius PI)))
  (circumference [this]
    (let [PI 3.14]
      (* (* radius 2) PI))))

このように 円周率3.14 を PI として束縛してもいいが、下のように
javaの Math クラスの定数 PI を使うという手もある。

;; 円
(defrecord Circle [radius]
  Shape
  (area [this]
      (* radius radius Math/PI))
  (circumference [this]
      (* (* radius 2) Math/PI)))

辺 3 と 4 を持つ長方形 rect1 を定義する。

user=> (def rect1 (->Rect 3 4))
#'user/rect1

面積 area は次のようにして求めることができる。

user=> (area rect1)
12

また、周 circumference は以下である。

user=> (circumference rect1)
14

ドット表記であらわすこともできるみたい。

user=> (.area rect1)
12
user=> (.circumference rect1)
14

しかし、クロージャー本では、ドットなしで表記していた。

また、円 circle3 を次のように定義する。

user=> (def circle3 (->Circle 3))
#'user/circle3

user=> circle3
{:radius 3}

面積と周は、それぞれ次のようにして求めることができる。

user=> (area circle3)
28.274333882308138

user=> (circumference circle3)
18.84955592153876
プログラミング Clojure 第2版

Stuart Halloway / Aaron Bedra 著
川合史朗 訳
平成25年4月25日 第2版第1刷 発行
オーム社