2014-04-23-01-本気で move について考える - 3 - project-enigma

2014-04-23-01-本気で move について考える - 3

>> Site top >> weblog >> 月別アーカイブ >> 2014年04月のlog >> 2014-04-23-01-本気で move について考える - 3

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


本気で move について考える - 3

2014 年 04 月 23 日

さて、できるだけのことはやったつもり。では、できたこととできなかったことを。

 

数日前には、自分は以下のようなことを要件としていた。

  1. move の結果を代入元に指定することで、ムーブが実現できる。
  2. move の結果を他の処理に『渡す』ことができ、その先でムーブが実行できなければならない。
  3. 上記の方法で渡しても、普通の参照のようにも使えなければならない。
  4. 実際にムーブを実行する場合、もう一度 move を使う。

ひとまずのところ、1 と 2 はできたと思って良いだろう。ただし、setf では使えない。opr= でなければならないのだ。これが重要なポイントの1つだ。そして、3 は完全に無視してしまった。どう考えてもできるとは思えなかったからだ。4 については、やらなくてもできてしまい、やっても無害である。それもどうかと思うが、これも仕方ないかな、と思っている。

では、パフォーマンスはどうだろうか。そもそも、opr= による代入が一般的に( setf と比べれば)コスト高になりそうだったからムーブをなんとかして実現しようとしたはずだった。しかし今日までの間に、どういうわけだかムーブは opr= 経由でないと動作せず、しかも追加の __move-2 という総称関数コールを必要とすることになってしまったのだ。今の自分の力量ではこれが限界というところだが、もう少しエレガントに解決できたらいいのにとは思う。

それはさておき、ひとまず展開形を見てみよう。普通に move と opr= を利用してムーブを行う式を展開する。今使っているのは sbcl なので、sb-cltl2:macroexpand-all を使用している。なお、空の let は手作業で消し、しかも小文字に変えてある。だって大文字だとなんか読み難いんだもん。

* (sb-cltl2:macroexpand-all '(opr= vec1 (move vec2)))

=> (let ((#:new779
          (operator= vec1
                     (__move-1 (lambda (&optional (op '#:get750))
                                 (if (eq op '#:get750)
                                     vec2
                                     (let ((#:new780 op))
                                       (setq vec2 #:new780)
                                       nil)))))))
     (setq vec1 #:new779)
     vec1)

 

opr= マクロにも move マクロにも、まだ少し削れるところがあるがそれはさておいて、ポイントは以下の通り。

‥‥‥なんか、ものスゴく大変なことをしているような気がする。しかし、C++ で T t2 = std::move( t1 ); と書くのを模倣するとなると、これくらいしか思いつかないのだ。あ、それで思い出した。以下のことも考えないといけない。

続きはまた。

 

コメント

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

 

このページのタグ

Page tag : Common Lisp

Page tag : STLとその移植

 

 


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