scanl 相当を実装したので適当に遊んでみるテスト.
http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/*checkout*/cradle/cradle/libs/range/test/integration/lazy_list_to_exp_utf.cpp?content-type=text%2Fplain
MSVC7.1, 8.0, GCC4.0.x, 4.1.x でテスト済み.余計なものごちゃごちゃくっついているので分かりにくいですけれど,中核となっているのは
range::assign( range::iterating( as_pure( _1 + 1.0 ), 1.0 ) | range::view::transform( as_pure( 1.0 / _1 ) ) | range::view::scan_left( as_pure( _1 * _2 ), 1.0 ) | range::view::take_while( as_pure( _1 >= 1.0e-10 ) ) | range::view::scan_left( as_pure( _1 + _2 ), 0.0 ) , v );
の部分です. as_pure は無視してやってください.この1文でやっていることを簡単に説明すると以下のとおり.
- range::iterating( _1 + 1.0, 1.0 ) で 1, 2, 3, ... な無限遅延リストを作って,
- range::view::transform( 1.0 / _1 ) で逆数列
の無限遅延リストに変換して,
- range::view::scan_left( _1 * _2, 1.0 ) で階乗の逆数列
の無限遅延リストに変換して,
- range::view::take_while 使って適当な位置で止めて有限な遅延リストに変換して,
- range::view::scan_left( _1 + _2, 0.0 ) で最終的に (てきとーな位置で停止する) 自然対数の底
への収束列を作り出して
- range::assign で vector に代入
なんかこういう方向性で遊び倒して,最終的に iterator/range は無限遅延リストに肉薄するポテンシャルを持っているんだよ的な結論を導きたい.道具1つ1つ用意するのがすげー労力必要なんだけれどそんなことはキニシナイ.
ぷるぷるにゃー.