2016-12-14-01-pairクラスを刷新 - project-enigma

2016-12-14-01-pairクラスを刷新

>> Site top >> weblog >> 月別アーカイブ >> 2016年12月のlog >> 2016-12-14-01-pairクラスを刷新

最終更新日付:2016/12/14 00:05:00


pairクラスを刷新

2016 年 12 月 14 日

‥‥‥だけのつもりだったのに、なんだかオオゴトになってしまった。

そもそもの発端は、えぇと、なんだっけ。多分アレだ。stl:with_tie マクロだ。あれがなんだか非効率的に見えた。どうしてかっていうと、以下のように展開されるからだ。

(stl:with_tie (v1 v2) tpl
  (list v1 v2))

;=> (LET ((#:TPL524 TPL))
;     (SYMBOL-MACROLET ((V1 (CL-STL::__TIE-GET 0 #:TPL524))
;                       (V2 (CL-STL::__TIE-GET 1 #:TPL524)))
;       (LIST V1 V2)))

 

CL-STL::__TIE-GETsetf も定義されていて、これの呼び出しに展開されるようにシンボルマクロを用意してやれば stl:with_tie が実現できる。できるのだけれど、問題は CL-STL::__TIE-GET が総称関数だということだ。これは事実上 stl:get と同じなので、with_tie を使ったからといってパフォーマンス的に嬉しいことがおきるわけではない。単にシンタクス的にすっきりするだけのことだ。

では、なぜ with_tie の展開において総称関数である CL-STL::__TIE-GET を使う必要があったのか。それは、stl:with_tiestl:tuple だけでなく stl:pair も扱うことができるからだ。もっと言うならば、stl:tuplestl:pair では内部的な実装が違うからだ。stl:tuple はその内部で要素を配列で保有するが、stl:pair は2要素と決まっているため、クラスのスロットとして2つのメンバを持っている。そのような構成になっているため、総称関数を避けることができなかったのだ。

で、そういうことなら stl:pairstl:tuple 同様に配列で保有しちゃいましょうと。アロケート時のパフォーマンスは時間的にも空間的にも多少は落ちるけど、アクセスのパフォーマンスが上がるのであれば割にあう取引になるだろう。

そんなわけで、stl:pair の実装を変更。ミソは、クラスのアクセサメソッドが総称関数になるということだ。つまり、stl:tuplestl:pair で同じアクセサメソッド名にしてやれば、stl:tiestl:with_tie ではいきなり内部配列を取得できるわけ。

余談だが、似たようなことは stl:get にも言える。これは STL に合わせてインデックスパラメータが整数の即値か、または定数値であることを求めるためにマクロだが、内部的には総称関数だ。そして、その総称関数呼び出しの内部でクラスインスタンスのスロットメンバにアクセスするためにまた総称関数をコールする。つまり総称関数呼び出しが2重になるわけだな。これも変更し、内部配列を取得するための総称関数1回だけで済ませることができるようになる‥‥‥

そんなこんなで、先の stl:with_tie の呼び出しは以下のように展開されることになる。いいね。

(stl:with_tie (v1 v2) tpl
  (list v1 v2))

;=> (LET ((#:ARR4665 (CL-STL::__INNER-ARRAY TPL)))
;     (DECLARE (TYPE SIMPLE-VECTOR #:ARR4665))
;     (UNLESS (<= 2 (LENGTH #:ARR4665))
;       (ERROR 'CL-STL:OUT_OF_RANGE
;              :WHAT "Variable count to with_tie is out of range."))
;     (SYMBOL-MACROLET ((V1 (SVREF #:ARR4665 0))
;                       (V2 (SVREF #:ARR4665 1)))
;       (LIST V1 V2)))

 

ところが、意気揚々と修正をしているうちにマズいことに気付いた。なんとまぁ、stl:getstl:array にも使えるのだ。stl:tie では使えないけどね。やれやれ、というわけで、仕方なく stl:array の内部配列にアクセスするためのメソッド名も揃えることにした。上記展開形にあるように、CL-STL::__INNER-ARRAY だ。

こんな感じで、ひとまず修正は完了。テストには通っているので、あとは簡単にパフォーマンスの比較をして、改善と言えると判断すればコミットというところかな。

 

コメント

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

 

このページのタグ

Page tag : STLとその移植

Page tag : Common Lisp

 

 


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