2015-09-22-01-STL書籍の掲載コードをCL-STLで書いてみよう-3 - project-enigma

2015-09-22-01-STL書籍の掲載コードをCL-STLで書いてみよう-3

>> Site top >> weblog >> 月別アーカイブ >> 2015年09月のlog >> 2015-09-22-01-STL書籍の掲載コードをCL-STLで書いてみよう-3

最終更新日付:2015/09/22 17:48:03


STL書籍の掲載コードをCL-STLで書いてみよう-3

2015 年 09 月 22 日

とりあえず見つかった問題については対処した(つもり)なので、続きをやろうと思う。今回は、remove-if のイメージで連想コンテナから要素を除去する話。

まず、書籍に書かれていたのは以下のようなコードだった。簡単だが効率の悪い方法として紹介されているもので、std::remove_copy_if を使って別の連想コンテナに要素をコピーし、swap メソッドでもって入れ替えをする、というもの。

AssocContainer<int> c;
...
AssocContainer<int> goodValues;
std::remove_copy_if( c.begin(), c.end(),
                     std::inserter( goodValues, goodValues.end() ), badValue );

c.swap( goodValues );

 

これは CL-STL でも以下のようにできる。先日同様、lambda 式を使用している。

* (let ((c (new stl:set #{0 1 2 3 4 5 6 7 8 9} #'<))
        (good-values (new stl:set #'<)))
    (stl:remove-copy-if (stl:begin c) (stl:end c)
                        (stl:inserter good-values (stl:end good-values))
                        (lambda (v) (zerop (mod v 3))))
    (stl:swap c good-values)
    (stl:for (v c)
      (format t " ~A" v)))

;=> 1 2 4 5 7 8
;   NIL

 

昨日「連想コンテナがバグっている」と書いたが、上記でやっている inserter もできない状態だったのだ。それは直った。だから上記のコードが動作するようになっている。やれやれ。

で、次にコピーを発生させない方式だが、Effective STL では以下のように書かれている。ポイントは、erase メソッドによって反復子が無効化されることに注意してコーディングすることが重要だ、という話だな。erase メソッドの呼び出し部分で後置インクリメントをやっている部分がそれだ。ちなみに、転記が面倒だったので、i の宣言には auto を使わせてもらった。

AssocContainer<int> c;
...
for( auto i = c.begin(); i != c.end(); /* none */ ) {
    if( badValue( *i ) )
        c.erase( i++ );
    else
        ++i;
}

 

で、同じことを CL-STL でやってみようとすると以下のようになる。with-operators というのが気になるかもしれない。これは CL-STL が基盤として利用する CL-OPERATOR のマクロで、これによって *itr1 とか ++itr1 とかいった記述ができるようになる。

* (let ((c (new stl:set #{1 2 3 4 5 6 7 8 9 10} #'<)))
    (with-operators
        (stl:for (((itr1 (stl:begin c))
                   (itr2 (stl:end   c))) (_/= itr1 itr2) nil)
          (if (bad-value *itr1)
              (stl:erase c itr1++)
              ++itr1)))
    (stl:for (v c)
      (format t " ~A" v)))

;=> 1 2 4 5 7 8 10
;   NIL

 

うん、上手く動いているようだ‥‥‥と思うかもしれないがさにあらず。最初の例では 0 - 9 でやったにも関わらず、今回は 1 - 10 でやっていることに気付いただろうか。実は、0 - 9 でやったらバグを見つけてしまったのだ‥‥‥もう少し、頑張る必要がありそうだ。やれやれ。

 

コメント

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

 

このページのタグ

Page tag : STLとその移植

Page tag : Common Lisp

 

 


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