Next: 時間的関係, Previous: リレーションフレームワーク, Up: ライブラリモジュール - ユーティリティ [Contents][Index]
util.stream
- ストリームライブラリこのモジュールは遅延ストリームのライブラリを提供します。このモジュール
にはsrfi-40とsrfi-41で定義されている関数および構文が含まれています。
後者は(scheme stream)
としてR7RS largeの一部になっています。
Gaucheには遅延ストリームとリストを統合したような、組み込みの遅延シーケンスがあります (遅延シーケンス)参照。そちらは通常のリスト手続きを使って扱うことができます。 このモジュールで提供される遅延ストームは、遅延シーケンスより重く、 扱うために専用の手続きが必要です。ただ、要素の評価は必要になるぎりぎりまで遅延され (遅延シーケンスでは必要な要素のひとつ先まで評価されます)、またポータブルです。
• Stream primitives | ||
• Stream constructors | ||
• Stream binding | ||
• Stream consumers | ||
• Stream operations |
Next: Stream constructors, Previous: ストリームライブラリ, Up: ストリームライブラリ [Contents][Index]
[R7RS stream]
{util.stream}
objがutil.stream
の手続きによって作成されたストリームであ
る場合にかぎり#t
を返します。
[R7RS stream] {util.stream} NULLストリームのシングルトンインスタンス。
[R7RS stream] {util.stream} ストリームの基本構成子。objectをstreamの先頭に追加し、新し いストリームを返します。
[R7RS stream]
{util.stream}
objがNULLストリームの場合にのみ#t
を返します。
[R7RS stream]
{util.stream}
objがNULLストリームではないストリームのときにのみ#t
を返します。
[R7RS stream] {util.stream} ストリームsの最初の要素を返します。
[R7RS stream] {util.stream} ストリームsの最初の要素を除いた残りの要素をストリームとして 返します。
[SRFI-40] {util.stream} exprの遅延形式であるストリームを返します。
原則として、ストリームを生成する関数はすべからく結果を
stream-delay
でラップすべきです。
(以下に述べるstream-lambda
, stream-let
, stream-define
を
使う手もあります)。
[R7RS stream]
{util.stream}
ストリームを返す関数を作る簡易マクロです。
(stream-lambda formals body body2 …)
は
(lambda formals (stream-delay body body2 …))
と同じです。
Next: Stream binding, Previous: Stream primitives, Up: ストリームライブラリ [Contents][Index]
[SRFI-40] {util.stream} 要素がobj …であるような新しいストリームを返します。
註:これはsrfi-41 (scheme.stream
)のstream
とは異なります。
srfi-41の方はマクロで、引数の評価が遅延されます。srfi-41版はこのモジュールでは
stream+
と言う名前で提供されます。
(stream 1 2 3)) ⇒ a stream that contains (1 2 3) (stream 1 (/ 1 0))) ⇒ error
{util.stream} 要素がexpr …の結果であるような新たなストリームを作って返します。
これはsrfi-41(scheme.stream
)のstream
と同じです。
各exprはアクセスされるまで評価されません。
(define s (stream+ 1 (/ 1 0))) ;; doesn't yield an error
(stream-car s) ⇒ 1
(stream-cadr s) ⇒ error
[R7RS stream] {util.stream} 次の手順で生成される要素をもつ新たなストリームを作成して返します。
#f
が返されたら、ストリームはそこで終了です。
s
を現在のシード値として、(f s)
をストリームの
現在の要素とし、(g s)
を次のシード値とします。
seedはシード値の初期値を与えます。
註:残念なことに、この手続きは他の *-unfold
系手続きと異なる順序で
引数を取ります。他の手続きはp f g
(述語、値生成、シード生成) の順です。
さらに、他の手続きでは述語は停止する時に真を返します。
(stream->list (stream-unfold integer->char (cut < <> 58) (cut + 1 <>) 48)) ⇒ (#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
[SRFI-40] {util.stream} 互いに関連する n 本のストリームを生成します。それぞれの内容は fおよびseedを使って生成します。
fは現在のシード値とともに呼ばれ、n+1
個の値
を返します。
(f seed) => seed result_0 result_1 … result_n-1
最初の値は次のシード値になります。Result_kは以下の形式のどれかで なければなりません。
(val)
valはk-番目のストリームの次のcar部になります。
#f
k-番目のストリームの新しい情報はありません。
()
k-番目のストリームの最後に到達しました。
以下の例では2つのストリームが作られます。最初のものは奇数の無限ストリー ムで、2つめのものは偶数の無限ストリームです。
gosh> (define-values (s0 s1) (stream-unfoldn (lambda (i) (values (+ i 2) ;; next seed (list i) ;; for the first stream (list (+ i 1)))) ;; for the second stream 0 2)) #<undef> gosh> (stream->list (stream-take s0 10)) (0 2 4 6 8 10 12 14 16 18) gosh> (stream->list (stream-take s1 10)) (1 3 5 7 9 11 13 15 17 19)
[R7RS stream]
{util.stream}
stream-unfoldn
と似ていますが、結果のストリームの数は
fの戻り値の数により決定されます。詳しくは
上のstream-unfoldn
の説明を参照してください。
[R7RS stream] {util.stream} obj …を繰り返す無限ストリームを返します。
(stream->list 10 (stream-constant 1 2)) ⇒ (1 2 1 2 1 2 1 2 1 2)
{util.stream}
n個のinitを要素とする新しいストリームを生成します。
initが省略された場合#f
が使われます。nを負の値にする
と無限ストリームが生成されます。
{util.stream} n個の要素をもつ新しいストリームを生成します。k-番目の要素 は init-proc を k に適用して得られます。nを負の値にする と無限ストリームが生成されます。
{util.stream}
startからはじまり、stepずつ要素が増加する数値のストリーム
を生成します。ストリームの長さは非負の実数countを越えない最大の整数値です。
count, start, stepのデフォルト値はそれぞれ
+inf.0
, 0 および 1です。
startとstepが正確数で、countが正確数か無限大の場合、 正確数のストリームが作られます。そうでなければ非正確数のストリームになります。
[R7RS stream]
{util.stream}
startから始まりstepおきにendの手前まで続く実数のストリームを
作って返します。endが省略された場合は正の無限大が使われます。
stepが省略された場合、startがendより小さければ1
が、
大きければ-1が使われます。
startとstepが正確数で、endが正確数か無限大の場合は、 正確数のシーケンスが、そうでない場合は非正確数のシーケンスが生成されます。
R7RSのscheme.stream
では、end引数は必須です。
(stream->list (stream-range 0 10)) ⇒ (0 1 2 3 4 5 6 7 8 9)
[R7RS stream]
{util.stream}
もうひとつの数値シーケンス生成手続きです。i番目の項が
(+ start (* i step))
であるような無限シーケンスを返します。
stepが省略されたら1が使われます。
startとstepが正確数なら、正確数のシーケンスが、
そうでなければ非正確数のシーケンスが返されます。
[R7RS stream]
{util.stream}
seedを初期値とし、ひとつ前の要素sから次の要素を(f s)
で
計算するような無限長のストリームを返します。
(stream->list 5 (stream-iterate (cut cons 'x <>) '())) ⇒ (() (x) (x x) (x x x) (x x x x))
gauche.lazy
のliterate
も参照
(遅延シーケンスユーティリティ).
{util.stream}
(stream-cons b a)
のこと。利便性のためだけにある。
{util.stream} streamの前にelt …を連結した新しいストリームを生成し ます。
[R7RS stream] {util.stream} listの要素を要素とする新たなストリームを作って返します。
{util.stream} 文字列を文字のストリームに変換します。tail-streamが与えられた場合は、 文字ストリームの後にそれが付け加えられます。
(stream->list (string->stream "abc" (list->stream ’(1 2 3)))) ⇒ (#\a #\b #\c 1 2 3)
{util.stream}
string->stream
を(format fmt arg …)
に適用した結果の
ストリームを返します。
[R7RS stream]
{util.stream}
iportからreaderを使って読み出されるデータを要素とする新たなストリームを
作って返します。iportのデフォルトは現在の入力ポート、
readerのデフォルトはread-char
です。
readerがEOFを返したらストリームの終端となります (EOF自体は ストリームには含まれません)。 EOFに達してもポートはクローズされません。
もしcloser引数が与えられたら、それがiportを引数として EOFが読まれた直後に呼ばれます。そこでポートをクローズするこはできます。
readerとcloser引数はR7RSのscheme.stream
では
定義されない、Gaucheの拡張です。
{util.stream} ジェネレータgenが生成する値の列からなる遅延ストリームを作って返します。 ジェネレータは引数を取らない手続きで、呼ばれる度に値を返し、EOFを返すことで 終端を示すものです(EOFはストリームには含まれません)。 詳しくはジェネレータを参照してください。
似た手続きに、ジェネレータから遅延シーケンスを得るgenerator->lseq
も
あります(遅延シーケンス参照)。
{util.stream} イテレータiterから遅延シーケンスを作る手続きです。
iterは二つの引数nextとendを取る手続きです。 nextは一つの引数を取る手続き、endは引数を取らない手続きです。 iter手続きは、その中で何らかの値の集合に対して順にnext手続きを呼び、 最後にend手続きを呼びます。次はわざとらしい例です:
(stream->list (iterator->stream (lambda (next end) (for-each next '(1 2 3 4 5)) (end)))) ⇒ (1 2 3 4 5)
内部的に、iterator->stream
はいわゆる「イテレータの反転」テクニックを
使っていて、iterは必要なだけしかイテレーションを行いません。なので
iterは無限の要素を扱うこともできます。
例えば次の例では、iterは増加する整数に対してnextを無限に呼び出す
ようになっていますが、stream-take
によって最初の10要素しか計算されません。
(stream->list (stream-take (iterator->stream (lambda (next end) (let loop ((n 0)) (next n) (loop (+ n 1))))) 10)) ⇒ (0 1 2 3 4 5 6 7 8 9)
[R7RS stream] {util.stream} ストリーム内包表記。各要素がelt-exprで計算されるストリームを返します。 clauseはelt-exprのスコープを作り、繰り返しを制御します。 各clauseは以下の形のいずれかです:
(x in stream-expr)
stream-exprが返すストリームの各要素を、xに束縛して繰り返します。 変数xのスコープは後続のclauseおよびelt-exprです。
(x is expr)
変数xに値exprの結果を束縛します。xのスコープは 後続のclauseおよびelt-exprです。
expr
exprが#f
に評価されたらこの回は値を生成せずに打ちきられ、
次の繰り返しに進みます。
次の内包表記はピタゴラス数の無限シーケンスを生成します:
(define pythagorean-triples (stream-of (list a b c) (c in (stream-from 3)) (b in (stream-range 2 c)) (a in (stream-range 1 b)) (= (square c) (+ (square b) (square a))))) (stream->list 5 pythagorean-triples) ⇒ ((3 4 5) (6 8 10) (5 12 13) (9 12 15) (8 15 17))
Next: Stream consumers, Previous: Stream constructors, Up: ストリームライブラリ [Contents][Index]
[R7RS stream] {util.stream} ストリームを作って返す関数を手軽に定義するマクロです。 次のフォームと同じです:
(define (name . formals) (stream-delay (let () body body2 …)))
[R7RS stream] {util.stream} lazyなnamed-letによるループを書くときに便利なマクロです。次のフォームと同じです:
(let loop-var ((var init) …) (stream-delay (let () body body2 …)))
[R7RS stream]
{util.stream}
このマクロは簡単なパターンマッチングを使ってストリームの要素にアクセスします。
stream-exprはストリームを返す式でなければなりません。
各clauseは(pattern expr)
か
(pattern fender expr)
という形です。
入力ストリームは各patternに順マッチするかどうかテストされます。 patternには以下の形のいずれかです:
()
空のストリームとマッチします。
(p0 p1 …)
パターン内の要素の数と入力ストリームの要素数が一致した時にマッチします。
(p0 p1 … . pRest)
入力ストリームの要素数が、pRestを除いたパターン内の要素の数以上であれば マッチします。pRestにはストリームの残りがマッチします。
pRest
入力ストリーム全体とマッチします。
パターンの各要素は識別子かリテラルのアンダースコア_
です。
アンダースコア以外の識別子の場合は、それらが対応する入力ストリームの要素に
束縛された環境でfenderとexprが評価されます。
もしfenderがあれば、まずそれが評価され、#f
であったらそのclauseの
マッチは失敗となり、次のclauseが試されます。
そうでなければexprが評価され、その結果がstream-match
の結果となります。
入力ストリームの要素はマッチに必要なだけ取り出されます。
次の例は、ストリーム中の真の値の数を数えています:
(define (num-trues strm) (stream-match strm (() 0) ((head . tail) head (+ 1 (num-trues tail))) ((_ . tail) (num-trues tail)))) (num-trues (stream #f #f #t #f #t #f #t #t)) ⇒ 4
Next: Stream operations, Previous: Stream binding, Up: ストリームライブラリ [Contents][Index]
これらの手続きはストリームを取り、その要素を消費し尽します。
[R7RS stream] {util.stream} funcをstreamsの各要素に適用します。 streamsが終端に達したところで停止します。
[R7RS stream] {util.stream} fを現在のシード値とstreamの要素に適用し、その結果を次のシード値として streamが終端に達するまで繰り返します。最初のシード値はseed引数で与えられます。 最後のシード値が返されます。
註: fの引数順は、他の*-fold
系関数のそれと異なることに注意してください。
例えばfold
(リストをたどる手続き参照) では最初に要素、次にシード値が
渡されます。
(stream-fold - 0 (stream 1 2 3 4 5)) ⇒ -15
Previous: Stream consumers, Up: ストリームライブラリ [Contents][Index]
[R7RS stream] {util.stream} 与えられたstreamを全部つないだ新たなストリームを返します。
[R7RS stream]
{util.stream}
R7RS scheme.stream
はstream-concat
を定義しました。
Gaucheにはstream-concatenate
があったので互換性のためにそちらも残しています。
どちらも同じです。
streamsはストリームのストリームです。各ストリームを連結したストリームを作って
返します。stream-append
と違い、streamsは無限個のストリームを生成
することができます。
[R7RS stream] {util.stream} streamsの各要素にfuncを適用した値を要素とする新しいストリー ムを返します。
[R7RS stream]
{util.stream}
seed
、
(func seed e0)
、
(func (func seed e0) e1)
…
で構成されるストリームを返します。ここで
e0、e1 …は入力ストリームstreamの要素です。
streamが有限なら、その要素よりひとつ多い要素が出力ストリームには含まれます。
(stream->list (stream-scan xcons '() (stream 1 2 3 4 5))) ⇒ (() (1) (2 1) (3 2 1) (4 3 2 1) (5 4 3 2 1))
[R7RS stream] {util.stream} 入力ストリームの対応する要素のリストを要素とするストリームを作って返します。 入力ストリームのいずれかが終端に達した時に出力ストリームも終わります。
(stream->list (stream-zip (stream 1 2 3) (stream 'a 'b 'c 'd))) ⇒ ((1 a) (2 b) (3 c))
[R7RS stream] {util.stream} predをパスする要素のみからなる新しいストリームを返します。
{util.stream} 述語predを満たさない要素のみからなる新しいストリームを返します。
{util.stream} 二つのストリームを返します。最初のストリームはstreamの要素のうち 述語predを満たすもの、次のストリームはpredを満たさないもので構成されます。
[R7RS stream] {util.stream} ストリームをリストに変換します。最初の形式では、streamの全ての要素が 取り出されます (従ってstreamが無限ストリームであればこの関数は永遠に戻りません)。 二番めの形式では最大でn要素までがストリームから取り出されそのリストが返されます。 nは非負の正確な整数でなければなりません。
註:通常のSchemeの慣例では、省略可能なnはstreamの後に来ますが、 この関数はそうでないことに注意。
{util.stream} ストリームを文字列に変換します。 streamの全ての要素は文字でなければなりません。 そうでない場合はエラーが投げられます。
{util.stream}
streamを、文字#\n
が要素である箇所で分割し、
分割されたストリームのストリームを返します。#\n
自体は結果に含まれません。
(stream->list (stream-map stream->string (stream-lines (string->stream "abc\ndef\nghi")))) ⇒ ("abc" "def" "ghi")
{util.stream}
引数のストリームの全ての対応する要素がそれぞれ、2引数を取るelt=で比較して等しい場合に
#t
を、そうでなければ#f
を返します。
全てのstreamが無限である場合、この手続きは終了しません。
{util.stream}
streamの最初の方の要素をリストprefixと比較します。各要素は
elt=で比較されます。prefixと全てマッチしたら#t
を、
そうでなければ#f
を返します。最大でもprefixの要素分だけstreamから
要素が取り出されます。
…
{util.stream}
(stream-caar s)
= (stream-car (stream-car s))
etc.
[R7RS stream] {util.stream} ストリームのpos番目の要素を返します。posは非負の正確な整数でなければなりません。
{util.stream}
(stream-first s)
= (stream-ref s 0)
etc.
{util.stream}
Returns a new stream that consists of the first count elements
of the given stream. If the given stream has less than
count elements, the stream returned by stream-take
would raise an error when the elements beyond the original stream
is accessed. On the other hand, the stream returned by
stream-take-safe
will return a shortened stream when
the given stream has less than count elements.
(stream->list (stream-take (stream-iota -1) 10)) ⇒ (0 1 2 3 4 5 6 7 8 9) (stream-take (stream 1 2) 5) ⇒ stream (stream->list (stream-take (stream 1 2) 5)) ⇒ error (stream->list (stream-take-safe (stream 1 2) 5)) ⇒ (1 2)
Note: srfi-41 (scheme.stream
) also defines stream-take
, but
the argument order is reversed, and also it allows stream to have
less than count
elements.
{util.stream}
Returns a new stream that consists of the elements in the given
stream except the first count elements.
If the given stream has less than count elements,
stream-drop
returns a stream that raises an error
if its element is accessed, and stream-drop-safe
returns an empty stream.
Note: srfi-41 (scheme.stream
) also defines stream-drop
, but
the argument order is reversed, and also it allows stream to have
less than count
elements.
{util.stream} Returns a new stream in which element is inserted between elements of stream.
{util.stream} Split stream on elements that satisfy pred, and returns a stream of splitted streams. The delimiting element won’t be included in the result.
{util.stream} Returns the last element of stream. If stream is infinite, this procedure won’t return.
{util.stream} Returns a stream that contains the last count elements in stream. The count argument must be a nonnegative exact integer. If the length of stream is smaller than count, the resulting stream is the same as stream. If stream is infinite, this procedure won’t return.
{util.stream} Returns a stream which is the same as stream but without the last element. If stream is empty, an empty stream is returned.
{util.stream} Returns a stream which is the same as stream but without the last count elements. The count argument must be a nonnegative exact integer. If stream is shorter than count, a null stream is returned.
[R7RS stream] {util.stream} Returns the number of elements in stream. It diverges if stream is infinite.
{util.stream} Returns true iff the length of stream is greater than or equal to, and exactly equal to, n, respectively. These procedures only realizes stream up to n elements.
[R7RS stream] {util.stream} streamの要素を逆順にしたストリームを返します。tail-streamが与えられた 場合、逆順にしたストリームの後にそれ付け加えられます。
省略可能なtail-streamはGaucheの拡張です。詳しくは
reverse
の説明を参照してください (他のリスト手続き)。
{util.stream}
{util.stream}
{util.stream}
[R7RS stream] {util.stream}
[R7RS stream] {util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
{util.stream}
Previous: Stream consumers, Up: ストリームライブラリ [Contents][Index]