2015-07-12-01-インクリメント/デクリメント演算子の変更 - project-enigma

2015-07-12-01-インクリメント/デクリメント演算子の変更

>> Site top >> weblog >> 月別アーカイブ >> 2015年07月のlog >> 2015-07-12-01-インクリメント/デクリメント演算子の変更

最終更新日付:2015/07/12 22:57:49


インクリメント/デクリメント演算子の変更

2015 年 07 月 12 日

CL-OPERATOR、現在の operator_++ および operator_-- の設計では、integer に対する実装ができない。これをなんとかしたいと思ったわけだ。で、なんとかしてしまったという話。

integer に適用できない理由というのは、operator_++ などのメソッド実装だけで全てが実行できると仮定しているためだ。しかし、仮に integer で特定化した operator_++ を以下のように実装しても、何の効果もない。

(defmethod operator_++ ((v integer))
  (1+ v))

 

これは、呼び出し元で setf しないからだ。言い換えれば、これまでの operator_++はクラスインスタンスが渡されるものと決めてかかっていたのだ。その前提があれば、渡されたインスタンスのスロットを変更するだけで呼び出し元に影響は波及する。しかし、integer のようなモノはそうはいかない。そこで、仕様を operator_+= などと同じように考えることにする。つまり、略記マクロに仕事をさせるのだ。以下のように。

(defmacro-overload _++ (sym)
  (check-type sym symbol)
  `(setf ,sym (operator_++ ,sym)))

 

そして、ついでなので後置演算子のためのメソッドを実装しなくても良いようにしよう。以下のようにする。後置インクリメント/デクリメントの略記マクロを以下のようにする。

(defmacro-overload _++ (sym dummy)
  (declare (ignore dummy))
  (check-type sym symbol)
  `(prog1 (clone ,sym)
     (setf ,sym (operator_++ ,sym))))

 

まとめると、以下のようになる。operator_-- も同様だ。

(defgeneric operator_++ (x))
(defgeneric operator_-- (x))

(defmethod operator_++ ((v integer)) (1+ v))
(defmethod operator_-- ((v integer)) (1- v))

(declare-macro-overload _++ (1 2))

(defmacro-overload _++ (sym)
  (check-type sym symbol)
  `(setf ,sym (operator_++ ,sym)))

(defmacro-overload _++ (sym dummy)
  (declare (ignore dummy))
  (check-type sym symbol)
  `(prog1 (clone ,sym)
     (setf ,sym (operator_++ ,sym))))

 

結果的に、operator_++ を直接コールした場合、効果が得られる保証はなくなる。しかし、これは operator_+= などでは以前からそうだった。これを機会に、「operator_foo を直接呼び出さないこと」というのをルール化する必要がある。

結果的に、後置インクリメント/デクリメントのためのオーバーロードは不要となり、operator_++ / operator_-- はオーバーロードメソッドではなくなった。そして、_++ / _-- の後置マクロは clone の実装を要求するようになったため、operator_clone のデフォルト実装(clone といいながらもただ渡されたモノを返すだけ)が必要となった。

まぁ大体こんなところだろうか。当たり前なのだけれど、インクリメント/デクリメントの後置演算子というのは移動前のコピーを作成して返すものなのでコスト高だ。C/C++/Java の世界では、その必要もないのに後置インクリメントを書く人を時々みかける。コンパイラが不要と判断して前置インクリメントに置き換えてくれるかもしれないが、まぁそれでもお行儀のいいものではない。そして Common Lisp 上の CL-OPERATOR では最適化は無理だろうから注意が必要だ。

 

コメント

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

 

このページのタグ

Page tag : Common Lisp

 

 


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