2014-11-26-01-lambdaでクラス - 3 - project-enigma

2014-11-26-01-lambdaでクラス - 3

>> Site top >> weblog >> 月別アーカイブ >> 2014年11月のlog >> 2014-11-26-01-lambdaでクラス - 3

最終更新日付:2014/11/26 16:40:05


lambdaでクラス - 3

2014 年 11 月 26 日

CL-CLASS というライブラリ、使い始めた途端におかしなところに気付く。なんとまぁ、コンストラクタの内部からパラメータにアクセスできないとな。

 

以下の非常に単純な例では、a と b にアクセスできない。

(class:define foo
  :constructors
  ((foo (a b) ()
        (print (+ a b)))))

 

これは、現状では以下のように展開されるからだ。ダメだね。

(let ()
  (cl-overload:declare-constructor foo (2))
  (labels ((#:foo-class762 ()
             (macrolet ()
               (labels ((#:object756 (#:this757 #:optype758 &rest #:args759)
                          (declare (ignorable #:this757 #:optype758 #:args759))
                          (ecase #:optype758
                            ((#:ctor-763)
                             (let ((cl-class:this #:this757))
                               (declare (ignorable cl-class:this))
                               (print (+ a b)))))))
                 #'#:object756))))
    (cl-overload:defmethod-constructor foo (a b)
      (let* ((#:this757 (#:foo-class762)))
        (funcall #:this757 #:this757 '#:ctor-763)
        #:this757))))

 

なんでこんなことになっているかというと、コンストラクタの内部からクラスのメンバメソッドをコール可能でなければならないという必要性から、コンストラクタの実装部分をクロージャ内部に移動したのだった( 上記コードの #:ctor-763 というやつ )。しかし、その際にコンストラクタに渡されるパラメータへのアクセスを確保しなかったという顛末。嗚呼。

色々面倒なので詳細は省くけれども、とにかく以下のように展開されるようにした。これでコンストラクタ内部からメンバメソッドやデータメンバにもアクセスできるし、コンストラクタパラメータにもアクセスできるわけだ。

(let ()
  (cl-overload:declare-constructor foo (2))
  (labels ((#:foo-class801 ()
             (macrolet ()
               (labels ((#:object795 (#:this796 #:optype797 &rest #:args798)
                          (declare (ignorable #:this796 #:optype797 #:args798))
                          (ecase #:optype797
                            ((#:ctor-802)
                             (destructuring-bind (a b) #:args798
                               (let ((cl-class:this #:this796))
                                 (declare (ignorable cl-class:this))
                                 (print (+ a b))))))))
                 #'#:object795))))
    (cl-overload:defmethod-constructor foo (a b)
      (let* ((#:this796 (#:foo-class801)))
        (funcall #:this796 #:this796 '#:ctor-802 a b)
        #:this796))))

 

 

コメント

このページにコメントする

 

このページのタグ

Page tag : Common Lisp

 

 


Copyright(C) 2005-2017 project-enigma.
Generated by CL-PREFAB.