Provided by: tcl8.6-doc_8.6.8+dfsg-3_all bug

NAME

       coroutine, yield, yieldto - Create and produce values from coroutines

SYNOPSIS

       coroutine name command ?arg...?
       yield ?value?
       yieldto command ?arg...?                                                                   │
       name ?value...?                                                                            │
_________________________________________________________________________________________________

DESCRIPTION

       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.

       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.

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

       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 yieldm {value} {                                                               │
                  yieldto return -level 0 $value                                                  │
              }                                                                                   │

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

       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.

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!"                          │

   DETAILED SEMANTICS
       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
              }

       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(3tcl), info(3tcl), proc(3tcl), return(3tcl)

KEYWORDS

       coroutine, generator