『プログラミング 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