Clojureでのクラスの操作

ウェブ技術 デジタルトランスフォーメーション技術 人工知能技術 自然言語処理技術 セマンティックウェブ技術 深層学習技術 オンライン学習&強化学習技術 チャットボットと質疑応答技術 ユーザーインターフェース技術 知識情報処理技術 推論技術  Clojure プログラミング

ClojurScriptを構成したり、Java等のOOPプラットフォームとの連携を考えたり、また前述のCralaでもClojureでのクラスの操作の理解が必要となる。

Clojureの「データ型:deftypeとdefrecordとretify」ではクラスの機能を提供する動機として、「強力で柔軟な抽象化とデータ構造定義のメカニズムをホストプラットフォームの機構に対して妥協することなく提供する」としている。ここで言うホストプラットフォーム主にjava等のOO(Object Oriented:オブジェクト指向)を指しており、それらの中で扱われているデータと整合性を持たせるための機構となる。

まずdeftypedefrecordについて。共に名前付きのフィールドを持つデータ構造を生成する点ではdefstructと似ているものとなる。defstructは以下のようにmapデータの構造を定義した後、それに合わせたデータを生成できる。これらは構造データを生成させるだけでクラスは生成せずOOには対応していない。

(defstruct person :name :age :height)
(struct person "george" 22 115)
;;-> {:name "george", :age 22, :height 115}

これに対して、deftypeやdefrecordを用いるとクラスが生成される。OOが持つ特性(プロトコルやインターフェース、インスタンスを持つ等)が利用可能となる。deftypeとdefrecordの違いは、deftypeが低レベルでの関数で、defrecordはdeftype上で構成されるものであるところにある。よって一般的なクラスの利用としては主にdefrecordが用いられ、例えば以下のようなクラスが生成される。

(defrecord Person [fname lname address])
(defrecord Address [city state zip])

これらを用いてインスタンスを生成する方法としては以下のように複数存在する。

(def sniper (new Person "bob" "swagger" (Address "Baltimore" "Maryland" 21080))
(def sniper (->Person "bob" "swagger" (Address "Baltimore" "Maryland" 21080))
(def sniper (Person. "bob" "swagger" (Address "Baltimore" "Maryland" 21080))

これらのデータにアクセスするには通常のmapと同様に以下のように行う。

(:lname sniper)
;;-> "swagger"
(-> sniper :address :city)
;;-> Baltimore"
(assoc sniper :fname "Lee")
;;#:user.Person{:fname "Lee", :lname "swagger", :address #:user.Address{:city "Baltimore", :state "Maryland", :zip 21080}}

ここでOOPのクラスに必要なメソッドの定義に関しては、まずdefprotocolで定義したプロトコル(インターフェース)をdefrecordに継承してメソッドの定義を行う形となる。具体的には以下のようなコードとなる。

(defprotocol WereCreature
   (full-moon-behavior [x])
(defrecord WereWolf [name title]
    WereCreature
      (full-moon-behavior [x]
         (str name " will howl and murder")))
(full-moon-behavior (map->WereWolf {:name "Lucian" :title "CEO of Merodrama"}))
;;-> "Lucian will howl murder"

この他に、クラスの継承やオーバーライドにはextendを利用したり、defrecordには初期化処理を記述するコンストラクターが無く初期化用の関数を予め定義する必要がある等いくつか考えなければいけないポイントがある。

 

コメント

  1. […] クラスの操作 ClojureでのOOP、mutableなデータの活用 […]

  2. […] nstを使用していくことになる。これがclojureのような完全なimmutableの世界だと”clojureでのクラスの操作“に述べたように、値が変わったオブジェクトのインスタンスを次々と生成し […]

タイトルとURLをコピーしました