2014-02-19-01-ファンクタの悩み - project-enigma

2014-02-19-01-ファンクタの悩み

>> Site top >> weblog >> 月別アーカイブ >> 2014年02月のlog >> 2014-02-19-01-ファンクタの悩み

最終更新日付:2014/02/19 23:50:00


ファンクタの悩み

2014 年 02 月 19 日

CL-STL のマニュアルを書いていて気付いた。そういえば、ファンクタが物凄くおろそかになっている。

というか、以前に一度「もうクロージャでいいじゃん」と思い切ってしまって、それっきりだったのだ。何を思い切ったのかというと、クロージャでは STL における関数オブジェクトのコピーの挙動を完全には模倣できないことだ。今回(と以後数回?)はこれについて書くことにしよう。

平たく言えば、模倣できない挙動というのは「状態を持つ関数オブジェクト」に関する問題だ。通常は関数オブジェクトに状態を持たせるのは良くない考えではあるが、いずれにせよそれは可能であるし、場合によっては有用でさえある。そして、C++ の世界では何も考えずに関数オブジェクトを引数渡しした場合、それは値渡しだ。しかし、状態を持つオブジェクトを値渡しした場合は当然ながらコピーが作成されるため、CL-STL はその挙動を模倣できなければならない。

実際問題として、これはそれほど問題にはならないのだが、要らざる非互換性は避けたい。そこで、クロージャ「しか使えない」現状を打破する方法を考えた。ファンクタの仕組みを CLOS を使って実装するのだ。

ベースとなるのは以下の総称関数の宣言。ファンクタをコピーするための functor-copy(これによって値渡しを模倣する)。そして、unary_function と binary_function を実装するための総称関数、およびその他だ。

(defgeneric functor-copy (func))
(defgeneric unary-function (func arg))
(defgeneric binary-function (func arg1 arg2))
(defgeneric polynominal-function (func &rest args))

「その他」とは、上記最後の polynominal-function だ。これはパラメータ数が1でも2でもないようなファンクタを使うためのもの。最終的にこれが CL-STL に追加されるかどうかはまだわからない。これは実験コードなので。

ファンクタを作成する場合、defclass でクラスを作成し、上記の総称関数を実装するメソッドを作ることになるが、ファンクタを呼び出す場合の記法は統一したい。そこで、以下の functor-invoke マクロを導入する。

(defmacro functor-invoke (func &rest args)
  (case (length args)
    (1 `(unary-function  ,func ,@args))
    (2 `(binary-function ,func ,@args))
    (t `(polynominal-function ,func ,@args))))

これで引数の数に応じて適切な総称関数の呼び出しに(コンパイル時点で)展開されるため、呼び出し元は常に functor-invoke だけを使っていられる。

しかし、Common Lisp を使っている以上、わざわざファンクタクラスを作成したりせずに lambda 式や関数を渡したいはずだ。だから、以下のような関数向けのデフォルトのメソッドを作成しておく。これによって、アルゴリズムなどに引き続き関数や lambda 式をそのまま渡すことができる。

(defmethod functor-copy ((func function))
  func)

(defmethod unary-function ((func function) arg)
  (funcall func arg))

(defmethod binary-function ((func function) arg1 arg2)
  (funcall func arg1 arg2))

(defmethod polynominal-function ((func function) &rest args)
  (apply func args))

‥‥‥続きは次回以降。

 

コメント

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

 

このページのタグ

Page tag : STLとその移植

 

 


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