For Gauche 0.9.10


Next: , Previous: , Up: ライブラリモジュール - ユーティリティ   [Contents][Index]

12.78 util.stream - ストリームライブラリ

Module: util.stream

このモジュールは遅延ストリームのライブラリを提供します。このモジュール にはsrfi-40とsrfi-41で定義されている関数および構文が含まれています。 後者は(scheme stream)としてR7RS largeの一部になっています。

Gaucheには遅延ストリームとリストを統合したような、組み込みの遅延シーケンスがあります (遅延シーケンス)参照。そちらは通常のリスト手続きを使って扱うことができます。 このモジュールで提供される遅延ストームは、遅延シーケンスより重く、 扱うために専用の手続きが必要です。ただ、要素の評価は必要になるぎりぎりまで遅延され (遅延シーケンスでは必要な要素のひとつ先まで評価されます)、またポータブルです。


Next: , Previous: , Up: ストリームライブラリ   [Contents][Index]

12.78.1 Stream primitives

Function: stream? obj

[R7RS stream] {util.stream} objutil.streamの手続きによって作成されたストリームであ る場合にかぎり#tを返します。

Variable: stream-null

[R7RS stream] {util.stream} NULLストリームのシングルトンインスタンス。

Macro: stream-cons object stream

[R7RS stream] {util.stream} ストリームの基本構成子。objectstreamの先頭に追加し、新し いストリームを返します。

Function: stream-null? obj

[R7RS stream] {util.stream} objがNULLストリームの場合にのみ#tを返します。

Function: stream-pair? obj

[R7RS stream] {util.stream} objがNULLストリームではないストリームのときにのみ#tを返します。

Function: stream-car s

[R7RS stream] {util.stream} ストリームsの最初の要素を返します。

Function: stream-cdr s

[R7RS stream] {util.stream} ストリームsの最初の要素を除いた残りの要素をストリームとして 返します。

Macro: stream-delay expr

[SRFI-40] {util.stream} exprの遅延形式であるストリームを返します。

原則として、ストリームを生成する関数はすべからく結果を stream-delayでラップすべきです。 (以下に述べるstream-lambda, stream-let, stream-defineを 使う手もあります)。

Macro: stream-lambda formals body body2 …

[R7RS stream] {util.stream} ストリームを返す関数を作る簡易マクロです。 (stream-lambda formals body body2 …)(lambda formals (stream-delay body body2 …))と同じです。


Next: , Previous: , Up: ストリームライブラリ   [Contents][Index]

12.78.2 Stream constructors

Function: stream obj …

[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
Macro: stream+ expr …

{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
Function: stream-unfold f p g seed

[R7RS stream] {util.stream} 次の手順で生成される要素をもつ新たなストリームを作成して返します。

註:残念なことに、この手続きは他の *-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)
Function: stream-unfoldn f seed n

[SRFI-40] {util.stream} 互いに関連する n 本のストリームを生成します。それぞれの内容は fおよびseedを使って生成します。

fは現在のシード値とともに呼ばれ、n+1個の値 を返します。

(f seed)
  => seed result_0 result_1 … result_n-1

最初の値は次のシード値になります。Result_kは以下の形式のどれかで なければなりません。

(val)

valk-番目のストリームの次の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)
Function: stream-unfolds f seed

[R7RS stream] {util.stream} stream-unfoldnと似ていますが、結果のストリームの数は fの戻り値の数により決定されます。詳しくは 上のstream-unfoldnの説明を参照してください。

Function: stream-constant obj …

[R7RS stream] {util.stream} obj …を繰り返す無限ストリームを返します。

(stream->list 10 (stream-constant 1 2))
  ⇒ (1 2 1 2 1 2 1 2 1 2)
Function: make-stream n :optional init

{util.stream} n個のinitを要素とする新しいストリームを生成します。 initが省略された場合#fが使われます。nを負の値にする と無限ストリームが生成されます。

Function: stream-tabulate n init-proc

{util.stream} n個の要素をもつ新しいストリームを生成します。k-番目の要素 は init-prock に適用して得られます。nを負の値にする と無限ストリームが生成されます。

Function: stream-iota :optional count start step

{util.stream} startからはじまり、stepずつ要素が増加する数値のストリーム を生成します。ストリームの長さは非負の実数countを越えない最大の整数値です。 count, start, stepのデフォルト値はそれぞれ +inf.0, 0 および 1です。

startstepが正確数で、countが正確数か無限大の場合、 正確数のストリームが作られます。そうでなければ非正確数のストリームになります。

Function: stream-range start :optional end step

[R7RS stream] {util.stream} startから始まりstepおきにendの手前まで続く実数のストリームを 作って返します。endが省略された場合は正の無限大が使われます。 stepが省略された場合、startendより小さければ1が、 大きければ-1が使われます。

startstepが正確数で、endが正確数か無限大の場合は、 正確数のシーケンスが、そうでない場合は非正確数のシーケンスが生成されます。

R7RSのscheme.streamでは、end引数は必須です。

(stream->list (stream-range 0 10))
 ⇒ (0 1 2 3 4 5 6 7 8 9)
Function: stream-from start :optional step

[R7RS stream] {util.stream} もうひとつの数値シーケンス生成手続きです。i番目の項が (+ start (* i step))であるような無限シーケンスを返します。 stepが省略されたら1が使われます。 startstepが正確数なら、正確数のシーケンスが、 そうでなければ非正確数のシーケンスが返されます。

Function: stream-iterate f seed

[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.lazyliterateも参照 (遅延シーケンスユーティリティ).

Function: stream-xcons a b

{util.stream} (stream-cons b a)のこと。利便性のためだけにある。

Function: stream-cons* elt … stream

{util.stream} streamの前にelt …を連結した新しいストリームを生成し ます。

Function: list->stream list

[R7RS stream] {util.stream} listの要素を要素とする新たなストリームを作って返します。

Function: string->stream string :optional tail-stream

{util.stream} 文字列を文字のストリームに変換します。tail-streamが与えられた場合は、 文字ストリームの後にそれが付け加えられます。

(stream->list (string->stream "abc" (list->stream ’(1 2 3)))) ⇒ (#\a #\b #\c 1 2 3)

Function: stream-format fmt arg …

{util.stream} string->stream(format fmt arg …)に適用した結果の ストリームを返します。

Function: port->stream :optional iport reader closer

[R7RS stream] {util.stream} iportからreaderを使って読み出されるデータを要素とする新たなストリームを 作って返します。iportのデフォルトは現在の入力ポート、 readerのデフォルトはread-charです。

readerがEOFを返したらストリームの終端となります (EOF自体は ストリームには含まれません)。 EOFに達してもポートはクローズされません。

もしcloser引数が与えられたら、それがiportを引数として EOFが読まれた直後に呼ばれます。そこでポートをクローズするこはできます。

readercloser引数はR7RSのscheme.streamでは 定義されない、Gaucheの拡張です。

Function: generator->stream gen

{util.stream} ジェネレータgenが生成する値の列からなる遅延ストリームを作って返します。 ジェネレータは引数を取らない手続きで、呼ばれる度に値を返し、EOFを返すことで 終端を示すものです(EOFはストリームには含まれません)。 詳しくはジェネレータを参照してください。

似た手続きに、ジェネレータから遅延シーケンスを得るgenerator->lseqも あります(遅延シーケンス参照)。

Function: iterator->stream iter

{util.stream} イテレータiterから遅延シーケンスを作る手続きです。

iterは二つの引数nextendを取る手続きです。 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)
Macro: stream-of elt-expr clause …

[R7RS stream] {util.stream} ストリーム内包表記。各要素がelt-exprで計算されるストリームを返します。 clauseelt-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: , Previous: , Up: ストリームライブラリ   [Contents][Index]

12.78.3 Stream binding

Macro: define-stream (name . formals) body body2 …

[R7RS stream] {util.stream} ストリームを作って返す関数を手軽に定義するマクロです。 次のフォームと同じです:

(define (name . formals)
  (stream-delay
    (let () body body2 …)))
Macro: stream-let loop-var ((var init) …) body body2 …

[R7RS stream] {util.stream} lazyなnamed-letによるループを書くときに便利なマクロです。次のフォームと同じです:

(let loop-var ((var init) …)
  (stream-delay
    (let () body body2 …)))
Macro: stream-match stream-expr clause …

[R7RS stream] {util.stream} このマクロは簡単なパターンマッチングを使ってストリームの要素にアクセスします。 stream-exprはストリームを返す式でなければなりません。 各clause(pattern expr)(pattern fender expr)という形です。

入力ストリームは各patternに順マッチするかどうかテストされます。 patternには以下の形のいずれかです:

()

空のストリームとマッチします。

(p0 p1 …)

パターン内の要素の数と入力ストリームの要素数が一致した時にマッチします。

(p0 p1 … . pRest)

入力ストリームの要素数が、pRestを除いたパターン内の要素の数以上であれば マッチします。pRestにはストリームの残りがマッチします。

pRest

入力ストリーム全体とマッチします。

パターンの各要素は識別子かリテラルのアンダースコア_です。 アンダースコア以外の識別子の場合は、それらが対応する入力ストリームの要素に 束縛された環境でfenderexprが評価されます。

もし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: , Previous: , Up: ストリームライブラリ   [Contents][Index]

12.78.4 Stream consumers

これらの手続きはストリームを取り、その要素を消費し尽します。

Function: stream-for-each func . streams

[R7RS stream] {util.stream} funcstreamsの各要素に適用します。 streamsが終端に達したところで停止します。

Function: stream-fold f seed stream

[R7RS stream] {util.stream} fを現在のシード値とstreamの要素に適用し、その結果を次のシード値として streamが終端に達するまで繰り返します。最初のシード値はseed引数で与えられます。 最後のシード値が返されます。

註: fの引数順は、他の*-fold系関数のそれと異なることに注意してください。 例えばfold (リストをたどる手続き参照) では最初に要素、次にシード値が 渡されます。

(stream-fold - 0 (stream 1 2 3 4 5))
  ⇒ -15

Previous: , Up: ストリームライブラリ   [Contents][Index]

12.78.5 Stream operations

Function: stream-append stream …

[R7RS stream] {util.stream} 与えられたstreamを全部つないだ新たなストリームを返します。

Function: stream-concat streams
Function: stream-concatenate streams

[R7RS stream] {util.stream} R7RS scheme.streamstream-concatを定義しました。 Gaucheにはstream-concatenateがあったので互換性のためにそちらも残しています。 どちらも同じです。

streamsはストリームのストリームです。各ストリームを連結したストリームを作って 返します。stream-appendと違い、streamsは無限個のストリームを生成 することができます。

Function: stream-map func stream stream2 …

[R7RS stream] {util.stream} streamsの各要素にfuncを適用した値を要素とする新しいストリー ムを返します。

Function: stream-scan func seed stream

[R7RS stream] {util.stream} seed(func seed e0)(func (func seed e0) e1) … で構成されるストリームを返します。ここで e0e1 …は入力ストリーム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))
Function: stream-zip stream …

[R7RS stream] {util.stream} 入力ストリームの対応する要素のリストを要素とするストリームを作って返します。 入力ストリームのいずれかが終端に達した時に出力ストリームも終わります。

(stream->list
 (stream-zip (stream 1 2 3) (stream 'a 'b 'c 'd)))
 ⇒ ((1 a) (2 b) (3 c))
Function: stream-filter pred stream

[R7RS stream] {util.stream} predをパスする要素のみからなる新しいストリームを返します。

Function: stream-remove pred stream

{util.stream} 述語predを満たさない要素のみからなる新しいストリームを返します。

Function: stream-partition pred stream

{util.stream} 二つのストリームを返します。最初のストリームはstreamの要素のうち 述語predを満たすもの、次のストリームはpredを満たさないもので構成されます。

Function: stream->list stream
Function: stream->list n stream

[R7RS stream] {util.stream} ストリームをリストに変換します。最初の形式では、streamの全ての要素が 取り出されます (従ってstreamが無限ストリームであればこの関数は永遠に戻りません)。 二番めの形式では最大でn要素までがストリームから取り出されそのリストが返されます。 nは非負の正確な整数でなければなりません。

註:通常のSchemeの慣例では、省略可能なnstreamの後に来ますが、 この関数はそうでないことに注意。

Function: stream->string stream

{util.stream} ストリームを文字列に変換します。 streamの全ての要素は文字でなければなりません。 そうでない場合はエラーが投げられます。

Function: stream-lines stream

{util.stream} streamを、文字#\nが要素である箇所で分割し、 分割されたストリームのストリームを返します。#\n自体は結果に含まれません。

(stream->list
 (stream-map stream->string
             (stream-lines (string->stream "abc\ndef\nghi"))))
 ⇒ ("abc" "def" "ghi")
Function: stream= elt= stream …

{util.stream} 引数のストリームの全ての対応する要素がそれぞれ、2引数を取るelt=で比較して等しい場合に #tを、そうでなければ#fを返します。 全てのstreamが無限である場合、この手続きは終了しません。

Function: stream-prefix= stream prefix :optional elt=

{util.stream} streamの最初の方の要素をリストprefixと比較します。各要素は elt=で比較されます。prefixと全てマッチしたら#tを、 そうでなければ#fを返します。最大でもprefixの要素分だけstreamから 要素が取り出されます。

Function: stream-caar s
Function: stream-cadr s

Function: stream-cdddar s
Function: stream-cddddr s

{util.stream} (stream-caar s) = (stream-car (stream-car s)) etc.

Function: stream-ref stream pos

[R7RS stream] {util.stream} ストリームのpos番目の要素を返します。posは非負の正確な整数でなければなりません。

Function: stream-first s
Function: stream-second s
Function: stream-third s
Function: stream-fourth s
Function: stream-fifth s
Function: stream-sixth s
Function: stream-seventh s
Function: stream-eighth s
Function: stream-ninth s
Function: stream-tenth s

{util.stream} (stream-first s) = (stream-ref s 0) etc.

Function: stream-take stream count
Function: stream-take-safe stream count

{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.

Function: stream-drop stream count
Function: stream-drop-safe stream count

{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.

Function: stream-intersperse stream element

{util.stream} Returns a new stream in which element is inserted between elements of stream.

Function: stream-split stream pred

{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.

Function: stream-last stream

{util.stream} Returns the last element of stream. If stream is infinite, this procedure won’t return.

Function: stream-last-n stream count

{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.

Function: stream-butlast stream

{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.

Function: stream-butlast-n stream count

{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.

Function: stream-length stream

[R7RS stream] {util.stream} Returns the number of elements in stream. It diverges if stream is infinite.

Function: stream-length>= stream n
Function: stream-length= stream n

{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.

Function: stream-reverse stream :optional tail-stream

[R7RS stream] {util.stream} streamの要素を逆順にしたストリームを返します。tail-streamが与えられた 場合、逆順にしたストリームの後にそれ付け加えられます。

省略可能なtail-streamはGaucheの拡張です。詳しくは reverseの説明を参照してください (他のリスト手続き)。

Function: stream-count pred stream …

{util.stream}

Function: stream-find pred stream

{util.stream}

Function: stream-find-tail pred stream

{util.stream}

Function: stream-take-while pred stream

[R7RS stream] {util.stream}

Function: stream-drop-while pred stream

[R7RS stream] {util.stream}

Function: stream-span pred stream

{util.stream}

Function: stream-break pred stream

{util.stream}

Function: stream-any pred stream …

{util.stream}

Function: stream-every pred stream …

{util.stream}

Function: stream-index pred stream …

{util.stream}

Function: stream-member obj stream :optional elt=
Function: stream-memq obj stream
Function: stream-memv obj stream

{util.stream}

Function: stream-delete obj stream :optional elt=

{util.stream}

Function: stream-delete-duplicates stream :optional elt=

{util.stream}

Function: stream-grep re stream

{util.stream}

Function: write-stream stream :optional oport writer

{util.stream}


Previous: , Up: ストリームライブラリ   [Contents][Index]