lrangeというのを使ってみた。
前回の記事書いたら、shiroさんからコメントでlrangeというのを教えてもらったので使ってみた。
Function: lrange start :optional end step
startからstepづつ増加し、endを越える直前までの遅延数列を 返します。stepのデフォルトは1、endのデフォルトは無限大です。 endを省略すると無限数列になるので、REPLで安易に (lrange 0)など評価しないようにしましょう。
遅延数列ということで、普通のリストを作る処理とは違うらしい。
これはつまり、遅延シーケンスをcar、cdr、mapといった 通常のリスト処理手続きにそのまま渡せるということです。
らしいので、論よりコード、とりあえず使ってみることにした。
iotaと比較(?)してみる。
#!/usr/local/bin/gosh (define (main args) (for-each (^x (if (> x 10) (exit))) (iota 100000000)))
#!/usr/local/bin/gosh (define (main args) (for-each (^x (if (> x 10) (exit))) (lrange 0 100000000)))
それぞれこう書いた、スクリプトを適当に用意して実行時に-ptimeを使ってみた。
% gosh -ptime iota-test.scm
Profiler statistics (total 1152 samples, 11.52 seconds)
num time/ total
Name calls call(ms) samples
- -
iota 1 11520.0000 1152(100%)
variable? 23 0.0000 0( 0%)
cenv-lookup 20 0.0000 0( 0%)
pass5/rec 16 0.0000 0( 0%)
reset-lvars/rec 15 0.0000 0( 0%)
pass4/subst 15 0.0000 0( 0%)
pass3/rec 15 0.0000 0( 0%)
・・・
% gosh -ptime lrange-test.scm
Profiler statistics (total 0 samples, 0.0 seconds)
num time/ total
Name calls call(ms) samples
- -
variable? 47 0.0000 0( 0%)
cenv-lookup 40 0.0000 0( 0%)
pass5/rec 33 0.0000 0( 0%)
reset-lvars/rec 31 0.0000 0( 0%)
・・・
compiled-code-emit0oi! 12 0.0000 0( 0%)
(lrange gen-exacts) 12 0.0000 0( 0%)
%map1c 12 0.0000 0( 0%)
・・・
違いは一目瞭然、かな?リストを一度すべて作らなければならないiotaに比べるとこういう処理なら、lrangeとかの方が良さげ。
利点としては無限の数列などを取り扱いときなんかに重宝するのだろうか?
ちなみにiotaにもliotaというのがあるらしいですが、まだ使ってない。
ユーザーリファレンスの下の方に色々と例が書いてあるけど、読めてないので帰ってきてから読むことにする。