Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-12-13

CLOSチュートリアル (7)

| 17:26 | CLOSチュートリアル (7) - わだばLisperになる を含むブックマーク はてなブックマーク - CLOSチュートリアル (7) - わだばLisperになる

Common Lisp クックブックさんのところのCLOSのチュートリアルに新しい練習問題(CLOSチュートリアル - 4.6. 修飾子とメソッド結合)が出たので挑戦!。

問題.1

initialize-instance に :after メソッドを追加し、すべての aardvark をイギリスのケンブリッジ(Cambridge, England)から来たことにします。もう一つ、次の関係が成り立たなくなるようなメソッド(どんな修飾子をつけますか?)を追加しなさい。

解答.1

とりあえず、initialize-instanceと:afterの組み合わせで作成してみました。

(defmethod initialize-instance :after ((aardvark aardvark) &rest init-args)
  (declare (ignore init-args))
  (setf (slot-value aardvark 'comes-from) "Cambridge, England"))

animalクラスでcomes-fromは:readに指定されているので、(setf (comes-from aardvark) "Cambridge, England")はできないので、スロット変数を直に指定してちょっと強引に書き換え。これで良いんだろうか。もっと良い方法があるような…。

:accessorだったなら

(defmethod initialize-instance :after ((aardvark aardvark) &rest init-args)
  (declare (ignore init-args))
  (setf (comes-from aardvark) "Cambridge, England"))

でいけます。

;; 動作
(setf zot (make-instance 'aardvark :legs 4 :comes-from "Brittany"))

(comes-from zot)
;=> "Cambridge, England"

それで次は

(make-instance 'cannibal :diet (make-instance 'cannibal))

が成立しないようなメソッドということですが、とりあえず、cannibalクラスを定義して、

(defclass cannibal (mammal) ())

(defmethod initialize-instance :before ((cannibal cannibal) &rest init-args)
  (when (eq (class-of cannibal) (class-of (getf init-args :diet)))
    (error "Cannibal!, Cannibal!")))

と:beforeを使ってdiet引数に同じクラスが渡された場合にerrorになるようにメソッドを追加してみました。しかし、これで良いんだろうか。

;; 動作
(setq cannibal (make-instance 'cannibal :diet (make-instance 'cannibal)))
;=> エラー "Cannibal, Cannibal"

(setq cannibal (make-instance 'cannibal :diet "foo"))
;=> #<CANNIBAL #x30004393E88D>

問題.2

initialize-instance は、他のオブジェクトシステムのコンストラクタを強化したものと見ることもできます。ただし、CLOSにはデストラクタがありません。デストラクタがないのは問題ですか?

解答.2

まず、デストラクタがなんだか良く分からないので、とりあえず、Wikipediaで調べてみたところ、コンストラクタの逆で後始末をするものということで、「Javaではデストラクタは存在せず、近い機能に自動ガベージコレクションによって機能するファイナライザがある。」ってことなので、Common LispにもGCあることだし、GC任せってことでしょうか。