File: recursively.yo

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (61 lines) | stat: -rw-r--r-- 3,032 bytes parent folder | download | duplicates (3)
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
Now we change the non-recursive tt(recursiveCoro) coroutine into a recursively
called coroutine. To activate recursion tt(recursiveCoro) is modified by
adding some extra statements below line 8:
    verbinsert(-ns4 //def demo/recursive/recursivecoro.cc)

Recursion is activated when the parameter tt(recurse) is tt(true), which is
passed to tt(recursiveCoro) when initially called by tt(main). It is then
recursively called in line 13, now using tt(false) as its argument.  Consider
what happens when it's recursively called: the while-loop is entered and the
for-statement at line 5 is executed, `co_yielding' two values. Next, in line
10, the loop ends, terminating the recursion. This implicitly calls
tt(co_return). It's also possible to do that explicitly, using
        verb(    if (not recurse)
        co_return;)
    Going back to the initial call: once tt(rec) (line 13) is available, a
nested while-loop is entered (line 15), receiving the next value obtained by
the recursive call (line 17). That tt(next) call resumes the nested coroutine,
which, as just described, returns two values when executing line 5's
for-statement. But then, when it's resumed for the third time, it doesn't
actually tt(co_yield) a newly computed value, but calls tt(co_return) (because
of lines 10 and 11), thus em(ending) the recursive call. At that point 
the coroutine's tt(State) class's member tt(done) returns tt(true), which
value is available through tt(ret.done()) (line 18). Once that happens the
while loop at line 15 ends, and the non-recursive coroutine continues at line
24. If the recursively called coroutine em(does) compute a value,
tt(rec.done()) returns tt(false), and tt(value) produced by tt(rec) is
`co_yielded' by the non-recursively called coroutine, making it available to
tt(main). So in that latter case the value co_yielded by the recursively
called coroutine is co_yielded by the initially called coroutine, where it is
retrieved by tt(main): there's a sequence of tt(co_yield) statements from the
most deeply nested coroutine to the coroutine that's called by tt(main),
at which point the value is finally collected in tt(main).

The tt(next..done) implementation used here resembles the way streams are
read: first try to extract information from a stream. If that succeeds, use
the value; if not, do something else:
        verb(    while (true)
    {
        cin >> value;
        if (not cin)
            break;
        process(value);
    })
    Functions like tt(getline) and overloaded extraction operators may combine
the extraction and the test. That's of course also possible when using
coroutines. Defining tt(next) as
        verb(    bool Recursive::next(size_t *value) 
    {
        d_handle.resume();
        if (d_handle.done())        // no more values
            return false;
        *value = d_handle.promise().value();
        return true;
    })
  allows us to change the while loop at line 15 into:
        verb(    size_t value;
    while (rec.next(&value))
        co_yield value;)