summaryrefslogtreecommitdiffstats
path: root/doc/coroutine.n
blob: 4985e520ab1dedfa6796f59071441f8dda842771 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
'\"
'\" Copyright (c) 2009 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: coroutine.n,v 1.4 2009/11/01 00:27:29 dkf Exp $
'\" 
.so man.macros
.TH coroutine n 8.6 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
coroutine, yield \- Create and produce values from coroutines
.SH SYNOPSIS
.nf
\fBcoroutine \fIname command\fR ?\fIarg...\fR?
\fByield\fR ?\fIvalue\fR?
\fIname\fR ?\fIvalue\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBcoroutine\fR command creates a new coroutine context (with associated
command) named \fIname\fR and executes that context by calling \fIcommand\fR,
passing in the other remaining arguments without further interpretation. Once
\fIcommand\fR returns normally or with an exception (e.g., an error) the
coroutine context \fIname\fR is deleted.
.PP
Within the context, values may be generated as results by using the
\fByield\fR command; if no \fIvalue\fR is supplied, the empty string is used.
When that is called, the context will suspend execution and the
\fBcoroutine\fR command will return the argument to \fByield\fR. The execution
of the context can then be resumed by calling the context command, optionally
passing in the value to use as the result of the \fByield\fR call that caused
the context to be suspended. If the coroutine context never yields and instead
returns conventionally, the result of the \fBcoroutine\fR command will be the
result of the evaluation of the context.
.PP
The coroutine can also be deleted by destroying the command \fIname\fR, and
the name of the current coroutine can be retrieved by using \fBinfo
coroutine\fR. 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).
.PP
At the point when \fIcommand\fR is called, the current namespace will be the
global namespace and there will be no stack frames above it (in the sense of
\fBupvar\fR and \fBuplevel\fR). However, which command to call will be
determined in the namespace that the \fBcoroutine\fR command was called from.
.SH EXAMPLES
.PP
This example shows a coroutine that will produce an infinite sequence of
even values, and a loop that consumes the first ten of them.
.PP
.CS
proc allNumbers {} {
    \fByield\fR
    set i 0
    while 1 {
        \fByield\fR $i
        incr i 2
    }
}
\fBcoroutine\fR nextNumber allNumbers
for {set i 0} {$i < 10} {incr i} {
    puts "received [\fInextNumber\fR]"
}
rename nextNumber {}
.CE
.PP
In this example, the coroutine acts to add up the arguments passed to it.
.PP
.CS
\fBcoroutine\fR accumulator apply {{} {
    set x 0
    while 1 {
        incr x [\fByield\fR $x]
    }
}}
for {set i 0} {$i < 10} {incr i} {
    puts "$i -> [\fIaccumulator\fR $i]"
}
.CE
.PP
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.
.PP
.CS
proc filterByFactor {source n} {
    \fByield\fR [info coroutine]
    while 1 {
        set x [\fI$source\fR]
        if {$x % $n} {
            \fByield\fR $x
        }
    }
}
\fBcoroutine\fR allNumbers apply {{} {while 1 {\fByield\fR [incr x]}}}
\fBcoroutine\fR eratosthenes apply {c {
    \fByield\fR
    while 1 {
        set n [\fI$c\fR]
        \fByield\fR $n
        set c [\fBcoroutine\fR prime$n filterByFactor $c $n]
    }
}} allNumbers
for {set i 1} {$i <= 20} {incr i} {
    puts "prime#$i = [\fIeratosthenes\fR]"
}
.CE
.SS "DETAILED SEMANTICS"
.PP
This example demonstrates that coroutines start from the global namespace, and
that\fIcommand\fR resolution happens before the coroutine stack is created.
.PP
.CS
proc report {where level} {
    # Where was the caller called from?
    set ns [uplevel 2 {namespace current}]
    \fByield\fR "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 [\fBcoroutine\fR coroEg example]
    }
    makeExample
}
.CE
.PP
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).
.PP
.CS
making from 2
made inner 1 context=:: name=::demo::coroEg
.CE
.SH "SEE ALSO"
apply(n), info(n), proc(n), return(n)
.SH KEYWORDS
coroutine, generator
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End: