| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In Scheme, procedures are fundamental blocks to build a program (See section 手続きを作る). A procedure represents a certain computation, possibly parameterized, and can be applied to the actual arguments to execute the computation. Scheme also provides the means to extract the continuation of the current computation and wraps it in a procedure (See section 継続).
Gauche extends the concept of procedure application, allowing
you to apply any object; for example, you can set up Gauche to
accept ("abc" 2) can be a valid application syntax.
See section 適用可能なオブジェクト, for the details.
| 6.18.1 Procedure class and applicability | ||
| 6.18.2 万能アクセサ | ||
| 6.18.3 コンビネータ | ||
| 6.18.4 省略可能引数のパージング | ||
| 6.18.5 手続きのアリティ | ||
| 6.18.6 適用可能なオブジェクト | ||
| 6.18.7 継続 | ||
| 6.18.8 多値 | ||
| 6.18.9 生成された値の畳み込み |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
手続きのクラスです。lambdaで作られた手続きや
組み込みのプリミティブ手続きはこのクラスのインスタンスです。
Gaucheではどんな型のオブジェクトも適用可能にできるので、あるオブジェクトが
<procedure>クラスのインスタンスであるかとうかということは
あまり気にする必要はありません。Gaucheの中身をいじってみる時以外は。
[R5RS]
objが生得的に適用可能なオブジェクトであれば#tを、
そうでなければ#fを返します。生得的にというのは、
Gaucheが最初から手続きとして呼び出せるオブジェクトとして備えているもの、程度の意味です。
<procedure>クラスのインスタンスや、
ジェネリックファンクションやメソッドがそうです。
(ジェネリックファンクションとメソッドに関しては
ジェネリックファンクションとメソッドを参照してください)。
Gaucheでは、どんなオブジェクトも適用可能にすることができます
(適用可能なオブジェクト参照)。従って、procedure?が#fを
返したからといってそのオブジェクトを手続きのように呼び出せないとは限りません。
オブジェクトが適用可能かどうかをより正確に調べるには、
下に説明するapplicable?を使ってください。
[R5RS]
(arg1 … . args)を引数として手続きprocを呼びます。
最後の引数argsは正規のリストでなければなりません。 procが返す
値をそのまま返します。
(apply list 'a 'b '(c d e)) ⇒ (a b c d e) (apply + 1 2 '(3 4 5)) ⇒ 15 |
それぞれの型がclass …であるような引数リストを伴って
objを呼び出すことができるかどうかを調べます。
例えば(applicable? foo <string> <integer>)が#tを
返したなら、fooを(foo "x" -2)のように呼び出せるということです。
(これは、エラーが出ないことを保証するものではありません。fooは
もしかする非負整数しか受け取れないかもしれませんが、そのことは
applicable?の結果からはわかりません。でも、applicable?が#tを
返したなら、fooを呼び出した時に“foo is not applicable”と
Gaucheに文句を言われることはありません。)
この手続きは適用可能オブジェクトも考慮に入れます。
従って、例えば(applicable? #/a/ <string>)は#tを返します。
正規表現は文字列に適用可能だからです (正規表現参照)。
ジェネリックファンクションに対しては、
渡されたclass引数それぞれが、対応する特定化子と一致するかサブクラスになっている
ようなメソッドが最低ひとつあれば、applicable?は#tを返します。
(define-method foo ((x <sequence>) (y <integer>)) #f) (applicable? foo <sequence> <integer>) ⇒ #t (applicable? foo <string> <integer>) ⇒ #t (applicable? foo <hash-table> <integer>) ⇒ #f (applicable? foo <string> <real>) ⇒ #f |
2番目の例では、<string>は<sequence>のサブクラスなので
#tが返ります。一方、3番目の例では<hash-table>は
<sequence>のサブクラスではないので#fとなります。
4番めの例が#fなのは、<real>が<integer>のサブクラスではないからです。
伝統的なSchemeの手続き (lambdaで作られるようなもの) は
引数の数のみで呼び出し可能かどうかが判断されます。オブジェクトが
引数の型にかかわらず、特定の個数の引数を取るかどうかを判定するには、
class引数に<top>を渡します。(<top>は
全てのクラスのスーパークラスです。)
(applicable? cons <top> <top>) ⇒ #t |
逆に、何らかの特定の型の引数を取るかどうかを調べたい場合は、
<bottom>を渡してください。(<bottom>は全てのクラスのサブクラスです。)
(define-method foo ((x <sequence>) (y <integer>)) #f) (applicable? foo <top> <top>) ⇒ #f (applicable? foo <bottom> <bottom>) ⇒ #t |
<top>, <bottom>クラスおよびGaucheでの型の扱いについては
型とクラスを参照してください。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
手続き~は、様々な集合型のオブジェクトの部分にアクセスするのに使えます。
;; Access to an element of a sequence by index (~ '(a b c) 0) ⇒ a (~ '#(a b c) 2) ⇒ c (~ "abc" 1) ⇒ #\b (~ '#u8(10 20 30) 1) ⇒ 20 ;; Access to an element of a collection by key (~ (hash-table 'eq? '(a . 1) '(b . 2)) 'a) ⇒ 1 ;; Access to a slot of an object by slot name (~ (sys-localtime (sys-time)) 'hour) ⇒ 20 |
アクセスはチェインすることができます。
(~ '#((a b c) (d e f) (g h i)) 1 2) ⇒ f (~ (hash-table 'eq? '(a . "abc") '(d . "def")) 'a 2) ⇒ #\c |
~は左結合します。つまり、
(~ x k j) ≡ (~ (~ x k) j) |
等。
一般化されたset!を~に使えば、アクセスされる要素を置き換えることができます。
(define z (vector 'a 'b 'c))
(set! (~ z 1) 'Z)
z ⇒ #(a Z c)
(define z (vector (list (vector 'a 'b 'c)
(vector 'd 'e 'f)
(vector 'g 'h 'i))
(list (vector 'a 'b 'c)
(vector 'd 'e 'f)
(vector 'g 'h 'i))))
z ⇒ #((#(a b c) #(d e f) #(g h i))
(#(a b c) #(d e f) #(g h i)))
(set! (~ z 1 2 0) 'Z)
z ⇒ #((#(a b c) #(d e f) #(g h i))
(#(a b c) #(d e f) #(Z h i)))
|
~は内部的にジェネリックファンクションrefを使って実現されています。
ジェネリックファンクションについて詳しくはオブジェクトシステムを参照してください。
多くの集合型はこのジェネリックファンクションを特殊化し、
統一されたアクセス方法と変更方法を提供しています。
refのオプショナル引数argsの意味はメソッド毎に異なりますが、
最初のオプショナル引数は、objectのkeyに対する値が無い場合の
フォールバック値として使われるのが普通です。
正確な動作の定義は、refメソッドを提供しているクラスごとに説明されています。
~の動作は次のコードで理解できるでしょう。
(define ~
(getter-with-setter
(case-lambda
[(obj selector) (ref obj selector)]
[(obj selector . more) (apply ~ (ref obj selector) more)])
(case-lambda
[(obj selector val) ((setter ref) obj selector val)]
[(obj selector selector2 . rest)
(apply (setter ~) (ref obj selector) selector2 rest)])))
|
(Gaucheは最適化のためにいくつかの型で短絡経路を使うこともあるので、 実際の実装とは異なります)
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Gaucheには、combinatory programmingに使えるいくつかの基本手続きがあります。
部分適用。手続きを返します。その手続きが引数m …を伴って
呼ばれた場合、それは(proc arg … m …)と等価になります。
(define add3 (pa$ + 3)) (add3 4) ⇒ 7 (map (pa$ * 2) '(1 2 3)) ⇒ (2 4 6) |
SRFI-26で定義されているマクロcutとcuteも似たような抽象化の
方法を提供しますが、pa$より多少柔軟性が高く、その分やや冗長です。
手続きを作るを参照して下さい。
apply, mapとfor-eachの部分適用版です。
(define map2* (map$ (pa$ * 2))) (map2* '(1 2 3)) ⇒ (2 4 6) |
SRFI-1(srfi-1 - List library参照)の手続に対応する部分適用版手続。
複数の手続きを結合します。引数は全て手続きでなければなりません。
2つの引数が渡された時、(.$ f g)は次の式と等価です。
(lambda args (call-with-values (lambda () (apply g args)) f)) |
2つ以上の引数が渡された場合は、次のように結合されます。
(.$ f g h ...) ≡ (.$ (.$ f g) h ...) |
いくつか例を示します。
(define not-zero? (.$ not zero?)) (not-zero? 3) ⇒ #t (not-zero? 0) ⇒ #f (define dot-product (.$ (apply$ +) (map$ *))) (dot-product '(1 2 3) '(4 5 6)) ⇒ 32 |
境界のケース:ひとつだけ引数が渡された場合は、その引数がそのまま返されます。 引数が全く渡されなかった場合は手続きvaluesが返されます。
註: .$という名前は、文献やいくつかの他のプログラミング言語で
.が関数合成によく使われること、そしてGaucheではコンビネータの末尾に
$をつける習慣があることから来ています。ただ、これはR5RS/R6RSの
範囲内では有効な識別子でないので、ポータビリティを考えるプログラムは
別名のcomposeを使った方が良いでしょう。そうすればsrfi-0などを
使って容易に移植が可能です。
述語predの意味を逆にした手続きを返します。すなわち、predが真を 返すような引数にたいして偽を返す、またその逆も同様であるような手続きです。
(map (complement even?) '(1 2 3)) ⇒ '(#t #f #t) (map (complement =) '(1 2 3) '(1 1 3)) ⇒ '(#f #t #f) ((complement (lambda () #f))) ⇒ #t |
与えられた引数をそれぞれ述語predに適用する手続きを返します。
いずれかのpredが#fでない値を返す場合、その値を返します。
全てのpredが#fを返す場合、#fを返します。
(define string-or-symbol? (any-pred string? symbol?))
(string-or-symbol? "abc") ⇒ #t
(string-or-symbol? 'abc) ⇒ #t
(string-or-symbol? 3) ⇒ #f
(define <> (any-pred < >))
(<> 3 4) ⇒ #t
(<> 3 3) ⇒ #f
((any-pred (cut memq <> '(a b c))
(cut memq <> '(1 2 3)))
'b) ⇒ '(b c)
|
与えられた引数をそれぞれ述語predに適用する手続きを返します。
全てのpredが#fでない値を返す場合、戻り値は最後の
predの戻り値になります。いずれかのpredが#fを
返す場合、every-predはそれ以降のpredを呼び出さずに
#fを返します。
((every-pred odd? positive?) 3) ⇒ #t ((every-pred odd? positive?) 4) ⇒ #f ((every-pred odd? positive?) -3) ⇒ #f (define safe-length (every-pred list? length)) (safe-length '(a b c)) ⇒ 3 (safe-length "aaa") ⇒ #f |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Gaucheは省略可能引数やキーワード引数を拡張lambda構文で サポートしています (手続きを作る参照)。 けれども、Gauche拡張に頼らずに、以下のマクロを使って独自にこれらの引数を パーズすることもできます。
(define (foo a b :optional (c #f) (d 'none))
body ...)
;; は次の式とだいたい同じ:
(define (foo a b . args)
(let-optionals* args ((c #f) (d 'none))
body ...))
|
明示的に拡張引数をパーズする方法は、ポータブルなコードを書く時に 役に立つでしょう。以下のマクロを実装するのは、lambdaの構文を 拡張するより簡単だからです。
また、共通する拡張引数の処理ルーチンを括り出す場合にもこれらのマクロは有用です。
与えられた値のリストrestargsを、var-specにしたがって 変数に束縛し、bodyを評価します。
var-specはシンボルか、そのcarがシンボルである2要素のリストの いずれかです。シンボルは束縛された変数名です。 restargsにある値は、順番にシンボルに束縛されます。 restargsにvar-specに示される数の値がない場合は、 残りのsymbolは以下に従ってデフォルト値が束縛されます。 var-specが単なるシンボルなら、デフォルト値は未定義です。 var-specがリストなら、デフォルト値はリストの2番目の要素を 評価した結果です。後者の場合、2番目の要素は十分な引数がない場合にのみ 評価されます。 束縛はvar-specの順番にしたがって行われるので、2番目の要素は 以前のvar-specのバインディングを参照するかも知れません。
2番目のフォームでは、restvarはシンボルでなければならず、 var-specに束縛された後、restargsに残っている値のリストに 束縛されます。
restargがvar-specよりも多い値を持っていてもエラーでは ありません。最初のフォームでは、余分な値は単に無視されます。
(define (proc x . args)
(let-optionals* args ((a 'a)
(b 'b)
(c 'c))
(list x a b c)))
(proc 0) ⇒ (0 a b c)
(proc 0 1) ⇒ (0 1 b c)
(proc 0 1 2) ⇒ (0 1 2 c)
(proc 0 1 2 3) ⇒ (0 1 2 3)
(define (proc2 . args)
(let-optionals* args ((a 'a) . b)
(list a b)))
(proc2) ⇒ (a ())
(proc2 0) ⇒ (0 ())
(proc2 0 1) ⇒ (0 (1))
(proc2 0 1 2) ⇒ (0 (1 2))
(define (proc3 . args)
(let-optionals* args ((a 0)
(b (+ a 1))
(c (+ b 1)))
(list a b c)))
(proc3) ⇒ (0 1 2)
(proc3 8) ⇒ (8 9 10)
(proc3 8 2) ⇒ (8 2 3)
(proc3 8 2 -1) ⇒ (8 2 -1)
|
これはlet-optionals*の短いバージョンで、オプショナル引数が 1つしかないときに使います。オプショナル引数のリストとしてrestargsが 与えらると、このマクロはオプショナル引数が与えられていればその値を返し、 そうでなければdefaultの結果を返します。defaultはrestargsが 空リストでなければ評価されません。
(define (proc x . maybe-opt)
(let ((option (get-optional maybe-opt #f)))
(list x option)))
(proc 0) ⇒ (0 #f)
(proc 0 1) ⇒ (0 1)
|
このマクロはキーワード引数のためのものです。var-specは 以下のフォームのうちのいずれかです。
(symbol expr)restargがsymbolと同じ名前を持つキーワードを含んでいる場合、 symbolを対応する値に束縛します。そのようなキーワードがrestargに ない場合は、symbolをexprの結果に束縛します。
(symbol keyword expr)restargがキーワードkeywordを含む場合、 symbolを対応する値に束縛します。そのようなキーワードがrestargに ない場合、symbolをexprの結果に束縛します。
デフォルト値exprは、restargにキーワードが与えられてなかった 場合にのみ評価されます。
1番目のフォームでは、var-specにないキーワード引数がrestargに 現れるとエラーとなります。 他のキーワード引数を許したい場合は次の2番目のフォームを使ってください。
2番目のフォームでは、restvarはシンボルか#fでなければなりません。
シンボルのときは、var-specに束縛されなかったrestargsのキーワード
リストがrestvarに束縛されます。#fのときは、それらのrestargs
のキーワードは単に無視されます。
(define (proc x . options)
(let-keywords options ((a 'a)
(b :beta 'b)
(c 'c)
. rest)
(list x a b c rest)))
(proc 0) ⇒ (0 a b c ())
(proc 0 :a 1) ⇒ (0 1 b c ())
(proc 0 :beta 1) ⇒ (0 a 1 c ())
(proc 0 :beta 1 :c 3 :unknown 4) ⇒ (0 a 1 3 (:unknown 4))
|
このマクロはlet-keywordsとほぼ同じですが、束縛がvar-specでの
順番に行われるところが異なります。exprは以前のvar-specにより
束縛された変数を参照できます。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
手続きのアリティを問い合わせるインターフェースです。 APIは、MzScheme (PLT Scheme)を参考にしました。
手続きprocを与え、整数、arity-at-leastオブジェクト、 整数とarity-at-leastオブジェクトからなるリストのいずれかを 返します。
整数の戻り値は、procが正確にその数の引数を取ることを表します。
arity-at-leastは、procが最低でも
引数(arity-at-least-value arity-at-least)を取ることを
表します。リストは、異なるアリティを持つ複数の手続きがあることを
表します。
Gaucheではいつでも、既存の手続きやジェネリック関数にメソッドを追加
できるので、arityが返す値はその手続きの現在の状態を示すに
過ぎません。その手続きやジェネリック関数に新しいメソッドが追加
されると、それも変更されます。
(arity cons) ⇒ 2 (arity list) ⇒ #<arity-at-least 0> (arity make) ⇒ (#<arity-at-least 1>) |
objがarity-at-leastオブジェクトなら、真を返します。
arity-at-leastオブジェクトが表す必須引数の数を返します。
手続きprocが引数kを取れる場合、#tを返します。
そうでなければ#fを返します。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Gaucheでは、特別な組み込みの機構によって任意のオブジェクトを 「適用可能」にすることができます。
手続きでもジェネリックファンクションでもないオブジェクトが何らかの引数に
適用されたとき、そのオブジェクトと引数がジェネリックファンクションobject-apply
に渡されます。
この機能は、具体的な例を挙げた方が説明し易いでしょう。
例えば、次のような式を評価しようとしたとします。
("abcde" 2)
|
オペレータは文字列に評価されますから、手続きでもジェネリックファンクションでも ありません。そこで、Gaucheはこの式を、あたかも次のような式が与えられた かのように解釈します。
(object-apply "abcde" 2) |
デフォルトでは、<string>と<integer>を引数とする
object-applyのメソッドは定義されていないので、
この式はエラーになります。しかし、次のようなメソッドを定義すると:
(define-method object-apply ((s <string>) (i <integer>)) (string-ref s i)) |
最初の式はまるで文字列が整数に適用されたかのように動作します。
("abcde" 2) ⇒ #\c
|
このメカニズムは手続きが許されるほとんどの箇所で使うことができます。
(apply "abcde" '(1)) ⇒ (#\b) (map "abcde" '(3 2 1)) ⇒ (#\d #\c #\b) |
Gauche組み込みオブジェクトのうち、<regexp>オブジェクトと
<regmatch>オブジェクトに対してはobject-applyメソッドが定義されて
います。正規表現を参照して下さい。
適用可能オブジェクトを適用するフォームがset!フォームの第一ポジションに
現れた場合、そのフォームは下に示すように展開され、このメソッドが呼ばれます。
(set! (object arg …) value) ⇒ ((setter object-apply) object arg … value) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[R5RS]
現在の継続を手続き (継続手続き) にパッケージ化して、それを引数として
procを呼び出します。procが戻ったら、その返り値がcall/ccの
値となります。作成された継続手続きがどこかで0個または複数個の引数を伴って呼ばれたら、
あたかもcall/ccから戻ったかのように実行が継続されます。その場合、
call/ccは、継続手続きに与えられた引数を複数の値として返します。
ファーストクラスの継続はSchemeの最も特徴的な機能のひとつですが、それを 十分に説明するにはこの本の余白は狭すぎます。適切なドキュメントを参照してください。
Schemeの継続とC言語の実行環境との間に、ちょっとわかりずらい干渉が生じることがあります。 次のシナリオを考えます。
継続を起動すること自体には問題は無いのですが、 制御がSchemeからCへと再び戻ろうとすると (つまり、step 3が再び実行されようとすると) 次のようなエラーが投げられます。
*** ERROR: attempt to return from a ghost continuation. |
これは、Cの世界では関数が1回より多く戻ってくることを想定していないからです。 最初にSchemeのコールバックが呼ばれた時のCのスタックフレームは、 継続が再び呼ばれた時には状態が変わっているか、捨てられてしまっているでしょう。
継続を、根から上へ向かって成長する制御フレームの連鎖のようにイメージした場合、 Cの世界へ戻った時点でその連鎖が断ち切られる、と考えることができます。 そのような根無しの継続も実行することはできますが、既に失った根に戻る前に 別の箇所へと制御を移さねばなりません。他の箇所で捕まえた継続を呼んだり、 例外を投げるといったことが考えられます。
部分継続(限定継続)を使うのも手です。
gauche.partcont - 部分継続を参照してください。
このマクロは次のように展開されます :
(call/cc (lambda (var) body …)).
APIはPLT Schemeから取りました。
[R5RS]
before、thunkおよびafter は引数を取らない手続きです。
dynamic-windはまずbeforeを呼び出し、続いてthunkを呼び出し、
続いてafterを呼び出します。そしてthunkが返した値を返します。
もしdynamic-windのダイナミックスコープの外で捕捉された継続が
thunkの中で呼ばれることにより制御がthunkから飛び出した場合、
(thunkの中でエラーが起こった場合などが考えられます)、
afterが呼ばれます。
もし、thunkの中で捕捉された継続がdynamic-windのダイナミックスコープの 外で呼ばれることにより制御がthunkの中へ飛び込んだ場合、 beforeが呼ばれます。
(letrec ((paths '())
(c #f)
(add (lambda (s) (push! paths s))))
(dynamic-wind
(lambda () (add 'connect))
(lambda ()
(add (call/cc (lambda (c0) (set! c c0) 'talk1))))
(lambda () (add 'disconnect)))
(if (< (length paths) 4)
(c 'talk2)
(reverse paths)))
⇒ (connect talk1 disconnect connect talk2 disconnect)
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[R5RS]
obj … を多値として返します。
呼び出し側は、組み込み構文の receive (変数束縛参照)か、
下に説明するR5RSの手続きcall-with-valuesを使って多値を受け取ることが
できます。
srfi-11 - Let-valuesも参照してください。
(values 1 2) ⇒ 1 and 2
|
[R5RS] 手続きproducerを引数無しで呼びます。そして、それが返した値 を引数としてconsumerを呼びます。consumerが返す値を 返します。
(call-with-values (lambda () (values 1 2)) cons) ⇒ (1 . 2) |
mv-exprが返す多値のk-番目の値を返します。概念としては、 以下のコードと同じです。
(call-with-values (lambda () mv-expr) (lambda r (list-ref r k))) |
このマクロは k がゼロであるような典型的な場合にはより単純な形へと 展開されます。
Common Lisp の nth-value に似ていますが、引数の順が逆になっています。
Scheme の他の*-ref 手続きと合わせるためです。
mv-exprを評価し、結果の値をリストにして返します。Common Lispで
multiple-value-listと呼ばれているものです。
(values->list (div-and-mod 10 3)) ⇒ (3 1) (values->list 1) ⇒ (1) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Sometimes a procedure is used as a generator of a series
of values, by yielding one value at a time. Customary an EOF
object is used to mark the end of the series. For example,
read-char is such a procedure that yields a series
of characters, terminated by EOF.
Since it is such a handy abstraction, Gauche provides a
set of utilties (see gauche.generator - ジェネレータ) to construct and generators
out of various sources, including other generators.
The generated values needs to be consumed eventually. Here we
provide several procedures to do that. These are useful
when combined with input procedures like read, so we
have them built-in instead of putting them in a separate module.
Works like fold on the generated values by generator
procedures gen gen2 … (See section リストをたどる手続き,
for the details of fold).
When one generator is given, for each value v generated by gen,
proc is called as (proc v r), where
r is the current accumulated result; the initial value of the
accumulated result is seed,
and the return value from proc becomes the next accumulated result.
When gen returns EOF, the accumulated result at that time is returned
from generator-fold.
When more than one generator is given, proc is
called as (proc v1 v2 … r),
where v1, v2 … are the values yielded from
gen, gen2, …, respectively, and r is
the current accumulated result. The iteration terminates when
any one of the generators returns EOF.
(with-input-from-string "a b c d e" (cut generator-fold cons 'z read)) ⇒ (e d c b a . z) |
Works like fold-right on the generated values by generator
procedures gen gen2 … (See section リストをたどる手続き,
for the details of fold-right).
This is provided for completeness, but it isn’t a good way to handle generators; in order to combine values right-associatively, we should read all the values from the generators (until any one of the generator returns EOF), then start calling proc as
(proc v0_0 v1_0 ... (proc v0_1 v1_1 ... (proc v0_n v1_n ... seed) ...)) |
where vn_m is the m-th value yielded by n-th generator.
(with-input-from-string "a b c d e" (cut generator-fold-right cons 'z read)) ⇒ (a b c d e . z) |
As you see, keeping all intermediate values kind of defeats the benefit of generators.
A generator version of for-each. Repeatedly applies proc on
the values yielded by gen, gen2 … until any one of
the generators yields EOF. The values returned from proc are discarded.
A generator version of map. Repeatedly applies proc on
the values yielded by gen, gen2 … until any one of
the generators yields EOF. The values returned from proc
are collected into a list and returned.
(with-input-from-string "a b c d e"
(cut generator-map symbol->string read))
⇒ ("a" "b" "c" "d" "e")
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on May 28, 2012 using texi2html 1.82.