## Tcl9.0.3/Tk9.0.3 Documentation > Tcl Commands > coroutine

### Tcl/Tk Applications | Tcl Commands | Tk Commands | [incr Tcl] Package Commands | SQLite3 Package Commands | TDBC Package Commands | tdbc::mysql Package Commands | tdbc::odbc Package Commands | tdbc::postgres Package Commands | tdbc::sqlite3 Package Commands | Thread Package Commands | Tcl C API | Tk C API | [incr Tcl] Package C API | TDBC Package C API

### NAME

coroutine, yield, yieldto, coroinject, coroprobe — コルーチンから値を創生育成する Create and produce values from coroutines

### 構文 SYNOPSIS

coroutine name command ?arg...?
yield ?value?
yieldto command ?arg...?
name ?value...?
coroinject coroName command ?arg...?
coroprobe coroName command ?arg...?

### 説明 DESCRIPTION

coroutine 命令は name と謂う名前の新しい(命令に結合した)コルーチン文脈を創生し､残りのその他の引数を更に解釈することなく渡しながら command を呼出す事によりその文脈を実行する｡一たび､ command が正常に戻るか､例外(譬えば､不都合)を伴って戻ると､コルーチン文脈の name は削除される｡　　　　　　　 The coroutine command creates a new coroutine context (with associated command) named name and executes that context by calling command, passing in the other remaining arguments without further interpretation. Once command returns normally or with an exception (e.g., an error) the coroutine context name is deleted.

文脈内部では､ yield 命令を使った結果として値が生成されてもよい; value が何も与えられない場合は空文字列が使われる｡呼出されると､その文脈は実行が棚上げされ､ coroutine 命令は引数を yield に返す｡文脈の実行は､文脈の命令を呼ぶことにより再開することができる､更に､文脈の棚上げを引起した yield 呼出しの結果として､使用すべき一つの値を渡すこともできる｡もしコルーチン文脈が yield を全く行わず､通常の方法で帰る場合は､その文脈の評価結果がその coroutine 命令の結果になる｡　　　　　 Within the context, values may be generated as results by using the yield command; if no value is supplied, the empty string is used. When that is called, the context will suspend execution and the coroutine command will return the argument to yield. The execution of the context can then be resumed by calling the context command, optionally passing in the single value to use as the result of the yield call that caused the context to be suspended. If the coroutine context never yields and instead returns conventionally, the result of the coroutine command will be the result of the evaluation of the context.

コルーチンは yieldto 命令の使用によっても実行が棚上げされる､その命令は戻る代りに､(コルーチンの文脈で決定された) command と呼ばれる命令に実行を譲り､それに幾つでも引数が手渡される｡全てのコルーチンは文脈命令を有するので､ yieldto は一つのコルーチンから別のコルーチンに制御を直接移転する為に使用でき(もし二つのコルーチンがその事態を予測している場合にのみ価値がある)､どのような命令も目標になりうる｡もしコルーチンがこの仕組みによって実行棚上げされている場合､そのコルーチンの処理は文脈命令の呼出により再開でき､指定すれば､任意個数の引数を手渡せる｡ yieldto 呼出しの返り値は文脈命令に渡した引数のリストである; それらの値で何を行うか決定することは呼出し側の責務である｡　　　　　　　　 The coroutine may also suspend its execution by use of the yieldto command, which instead of returning, cedes execution to some command called command (resolved in the context of the coroutine) and to which any number of arguments may be passed. Since every coroutine has a context command, yieldto can be used to transfer control directly from one coroutine to another (this is only advisable if the two coroutines are expecting this to happen) but any command may be the target. If a coroutine is suspended by this mechanism, the coroutine processing can be resumed by calling the context command optionally passing in an arbitrary number of arguments. The return value of the yieldto call will be the list of arguments passed to the context command; it is up to the caller to decide what to do with those values.

多重の引数を伴って再開を許可する yield の版を書く推奨方法は、このように、 yieldto および return 命令を使用して､この様に: 　　　　 The recommended way of writing a version of yield that allows resumption with multiple arguments is by using yieldto and the return command, like this:

    proc yieldMultiple {value} {
        tailcall yieldto string cat $value
    }

コルーチンは命令の名前 name を破棄することによっても削除され､又､現在のコルーチンの名前は info coroutine によって取出せる｡もし､コルーチンの実装内の変数の削除の追跡がある場合は､コルーチンが明示的に削除される時点で(又はより自然に､その命令が通常の方法で返った場合)､それらは開始されることになる｡ The coroutine can also be deleted by destroying the command name, and the name of the current coroutine can be retrieved by using info coroutine. If there are deletion traces on variables in the coroutine's implementation, they will fire at the point when the coroutine is explicitly deleted (or, naturally, if the command returns conventionally).

command が呼出された時点で､現在の名前空間は大域名前空間であり､そこには( upvar と uplevel の様な)棚枠はない｡しかし､コルーチン命令が呼出された名前空間の中で､どの命令を呼出すべきかが決定されることになる｡ 　　　 At the point when command is called, the current namespace will be the global namespace and there will be no stack frames above it (in the sense of upvar and uplevel). However, which command to call will be determined in the namespace that the coroutine command was called from.

中断されているコルーチン(即ち､yield やyieldto によって中断)は､コルーチンが留まっている時点で命令を実行すべき coroprobe の使用により､その時点での､検査された(又は修正された)状態を持ち得る｡ 命令は､命令を実行する為に､コルーチンの名前をとり､coroName と､その時点で直ぐに実行すべき命令(それが要求する何かの引数もあり得る)の名前である｡ その命令の結果は coroprobe 命令の結果であり､コルーチンの総体的状態は､ 縦え変数が変更されていても､その後と同じに留まる(即ち､コルーチンは猶も前の様に yield や yieldto の結果を期待している)｡ A suspended coroutine (i.e., one that has yielded or yieldto-d) may have its state inspected (or modified) at that point by using coroprobe to run a command at the point where the coroutine is at. The command takes the name of the coroutine to run the command in, coroName, and the name of a command (any any arguments it requires) to immediately run at that point. The result of that command is the result of the coroprobe command, and the gross state of the coroutine remains the same afterwards (i.e., the coroutine is still expecting the results of a yield or yieldto as before) though variables may have been changed.

同様に､ coroprobe とよく似ている coroinject 命令も､引数を処理する為に､中断されたコルーチン(続行される時)の内部で実行されるべく使用され得る｡但し coroinject では幾つかの重要な違いがある､即ち： Similarly, the coroinject command may be used to place a command to be run inside a suspended coroutine (when it is resumed) to process arguments, with quite a bit of similarity to coroprobe. However, with coroinject there are several key differences:

- コルーチンは挿入がなされた直後には続行されない｡コルーチンが続行される前に多重挿入がなされるのでこの結果になる｡挿入命令は定義の逆順に遂行される(即ち､内部では後入先出に貯蔵される)｡ The coroutine is not immediately resumed after the injection has been done. A consequence of this is that multiple injections may be done before the coroutine is resumed. The injected commands are performed in reverse order of definition (that is, they are internally stored on a stack).

- 追加的な二つの引数が実行されるべき引数のリストに追記される(即ち､命令とその引数は二つの要素により拡張される)｡第一はコルーチンの中断を惹き起こしている命令の名前(yield か yieldto)､第二は､現在続行中の値の引数(又は､yieldto の場合は引数のリスト)である｡ An additional two arguments are appended to the list of arguments to be run (that is, the command and its args are extended by two elements). The first is the name of the command that suspended the coroutine (yield or yieldto), and the second is the argument (or list of arguments, in the case of yieldto) that is the current resumption value.

- 挿入される命令の結果は､ コルーチンの中断状態を惹き起こした yield や yieldto の結果として使われる｡多重の挿入命令がある処では､一個の結果は次によって処理された続行の値になる｡ The result of the injected command is used as the result of the yield or yieldto that caused the coroutine to become suspended. Where there are multiple injected commands, the result of one becomes the resumption value processed by the next.

挿入は一回限りである｡一たび実行されると保持されない｡その実行の一部として yield や yieldto がなされる｡ The injection is a one-off. It is not retained once it has been executed. It may yield or yieldto as part of its execution.

註意､実行しているコルーチンは調査も挿入もされない；業務は､中断されているコルーチンのみに適用され得る｡(もしコルーチンが実行中であれば､どのような自己調査符号も単に､何処で現在実行しているかの状態を検査するのみ; この場合 coroinject/coroprobe は不要) Note that running coroutines may be neither probed nor injected; the operations may only be applied to coroutines that are suspended. (If a coroutine is running then any introspection code would be merely inspecting the state of where it is currently running; coroinject/coroprobe are unnecessary in that case.)

### 用例 EXAMPLES

この例は､無限の偶数列の並びの生成と､その初めの１０個を消費する繰返しのコルーチンを示す｡ 　　 This example shows a coroutine that will produce an infinite sequence of even values, and a loop that consumes the first ten of them.

    proc allNumbers {} {
        yield
        set i 0
        while 1 {
            yield $i
            incr i 2
        }
    }
    coroutine nextNumber allNumbers
    for {set i 0} {$i < 10} {incr i} {
        puts "received [nextNumber]"
    }
    rename nextNumber {}

この例では､コルーチンは渡された引数まで加えるように活動する｡ 　　 In this example, the coroutine acts to add up the arguments passed to it.

    coroutine accumulator apply {{} {
        set x 0
        while 1 {
            incr x [yield $x]
        }
    }}
    for {set i 0} {$i < 10} {incr i} {
        puts "$i -> [accumulator $i]"
    }

この例では､素数を見つける為の古典的なエラストネスの篩の算法を実現する為のコルーチンの使用を実証する｡註意すべきは､コルーチン内部のコルーチン作成である｡ 　　　 This example demonstrates the use of coroutines to implement the classic Sieve of Eratosthenes algorithm for finding prime numbers. Note the creation of coroutines inside a coroutine.

    proc filterByFactor {source n} {
        yield [info coroutine]
        while 1 {
            set x [$source]
            if {$x % $n} {
                yield $x
            }
        }
    }
    coroutine allNumbers apply {{} {while 1 {yield [incr x]}}}
    coroutine eratosthenes apply {c {
        yield
        while 1 {
            set n [$c]
            yield $n
            set c [coroutine prime$n filterByFactor $c $n]
        }
    }} allNumbers
    for {set i 1} {$i <= 20} {incr i} {
        puts "prime#$i = [eratosthenes]"
    }

この例が示すのは､互いに他を生成する三つのコルーチンの群の中で､如何に値を渡し得るかである: 　　　 This example shows how a value can be passed around a group of three coroutines that yield to each other:

    proc juggler {name target {value ""}} {
        if {$value eq ""} {
            set value [yield [info coroutine]]
        }
        while {$value ne ""} {
            puts "$name : $value"
            set value [string range $value 0 end-1]
            lassign [yieldto $target $value] value
        }
    }
    coroutine j1 juggler Larry [
        coroutine j2 juggler Curly [
            coroutine j3 juggler Moe j1]] "Nyuck!Nyuck!Nyuck!"

この例では､引数が与えられない時､非空の値を集めそのリストを返す単純なコルーチンを示す｡それは､それがしていることを見出す為にコルーチンをどうすれば覗き込むことができ､又､どうすれば入力を一回限りに修正できるかを示す｡ This example shows a simple coroutine that collects non-empty values and returns a list of them when not given an argument. It also shows how we can look inside the coroutine to find out what it is doing, and how we can modify the input on a one-off basis.

    proc collectorImpl {} {
        set me [info coroutine]
        set accumulator {}
        for {set val [yield $me]} {$val ne ""} {set val [yield]} {
            lappend accumulator $val
        }
        return $accumulator
    }

    coroutine collect collectorImpl
    collect 123
    collect "abc def"
    collect 456

    puts [coroprobe collect set accumulator]
    # ==> 123 {abc def} 456

    collect "pqr"

    coroinject collect apply {{type value} {
        puts "Received '$value' at a $type in [info coroutine]"
        return [string toupper $value]
    }}

    collect rst
    # ==> Received 'rst' at a yield in ::collect
    collect xyz

    puts [collect]
    # ==> 123 {abc def} 456 pqr RST xyz

#### 詳細な意味論 DETAILED SEMANTICS

この例が実証することは､コルーチンは大域名前空間から出発し､コルーチンの棚が作成される前に command の決定が生じていることである｡ 　　　　　　　　 This example demonstrates that coroutines start from the global namespace, and that command resolution happens before the coroutine stack is created.

    proc report {where level} {
        # Where was the caller called from?
        set ns [uplevel 2 {namespace current}]
        yield "made $where $level context=$ns name=[info coroutine]"
    }
    proc example {} {
        report outer [info level]
    }
    namespace eval demo {
        proc example {} {
            report inner [info level]
        }
        proc makeExample {} {
            puts "making from [info level]"
            puts [coroutine coroEg example]
        }
        makeExample
    }

それが作成する出力は下の通りである｡特に､棚の操作が起っていることが判る(第１行と第２行の水準の比較から)又､コルーチンの親の水準は大域名前空間である｡又コルーチンの名前は修飾されていない場合は現在の名前空間に対し局所的であり､コルーチンがその水準で yield 活動するかもしれない､ことが分かる(譬えば､呼出された手続函数内で)｡　　　　　　　　　 Which produces the output below. In particular, we can see that stack manipulation has occurred (comparing the levels from the first and second line) and that the parent level in the coroutine is the global namespace. We can also see that coroutine names are local to the current namespace if not qualified, and that coroutines may yield at depth (e.g., in called procedures).

    making from 2
    made inner 1 context=:: name=::demo::coroEg

### SEE ALSO

apply, info, proc, return

### KEYWORDS

coroutine, generator
Copyright © 2009 Donal K. Fellows.