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
|
<ppdoc>
<copyright>
Copyright (c) 2001 by Addison Wesley Longman. This
material may be distributed only subject to the terms and
conditions set forth in the Open Publication License, v1.0 or
later (the latest version is presently available at
http://www.opencontent.org/openpub/).
</copyright>
<class name="Continuation" super="Object" type="class">
<p/>
<classname>Continuation</classname> objects are generated by
<mim><file>kernel</file><front>Kernel</front><back>callcc</back><mref>callcc</mref></mim>. They hold a return address and execution
context, allowing a nonlocal return to the end of the <tt>callcc</tt>
block from anywhere within a program. Continuations are somewhat
analogous to a structured version of C's <tt>setjmp/longjmp</tt>
(although they contain more state, so you might consider them closer
to threads).
<p/>
For instance:
<p/>
<codefragment>
<alltt><fullcode><![CDATA[ arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|$cc|}
puts(message = arr.shift)
$cc.call unless message =~ /Max/
]]></fullcode>
arr<nbsp/>=<nbsp/>[<nbsp/>"Freddie",<nbsp/>"Herbie",<nbsp/>"Ron",<nbsp/>"Max",<nbsp/>"Ringo"<nbsp/>]
callcc{|$cc|}
puts(message<nbsp/>=<nbsp/>arr.shift)
$cc.call<nbsp/>unless<nbsp/>message<nbsp/>=~<nbsp/>/Max/
</alltt>
</codefragment>
<em>produces:</em>
<codefragment><alltt>
Freddie
Herbie
Ron
Max
</alltt>
</codefragment>
<p/>
This (somewhat contrived) example allows the inner loop to abandon
processing early:
<p/>
<codefragment>
<alltt><fullcode><![CDATA[ callcc {|cont|
for i in 0..4
print "\n#{i}: "
for j in i*5...(i+1)*5
cont.call() if j == 17
printf "%3d", j
end
end
}
print "\n"
]]></fullcode>
callcc<nbsp/>{|cont|
<nbsp/><nbsp/>for<nbsp/>i<nbsp/>in<nbsp/>0..4
<nbsp/><nbsp/><nbsp/><nbsp/>print<nbsp/>"\n#{i}:<nbsp/>"
<nbsp/><nbsp/><nbsp/><nbsp/>for<nbsp/>j<nbsp/>in<nbsp/>i*5...(i+1)*5
<nbsp/><nbsp/><nbsp/><nbsp/><nbsp/><nbsp/>cont.call()<nbsp/>if<nbsp/>j<nbsp/>==<nbsp/>17
<nbsp/><nbsp/><nbsp/><nbsp/><nbsp/><nbsp/>printf<nbsp/>"%3d",<nbsp/>j
<nbsp/><nbsp/><nbsp/><nbsp/>end
<nbsp/><nbsp/>end
}
print<nbsp/>"\n"
</alltt>
</codefragment>
<em>produces:</em>
<codefragment><alltt>
<p/>
0:<nbsp/><nbsp/><nbsp/>0<nbsp/><nbsp/>1<nbsp/><nbsp/>2<nbsp/><nbsp/>3<nbsp/><nbsp/>4
1:<nbsp/><nbsp/><nbsp/>5<nbsp/><nbsp/>6<nbsp/><nbsp/>7<nbsp/><nbsp/>8<nbsp/><nbsp/>9
2:<nbsp/><nbsp/>10<nbsp/>11<nbsp/>12<nbsp/>13<nbsp/>14
3:<nbsp/><nbsp/>15<nbsp/>16
</alltt>
</codefragment>
<p/>
<methods type="instance">
<method name="call" ref="call">
<callseq>
<obj>cont</obj>.call( <optz><obj>args</obj></optz> )
</callseq>
<desc>
<p/>
Invokes the continuation. The program continues from the end of
the <tt>callcc</tt> block. If no arguments are given, the original
<meth>callcc</meth> returns <const>nil</const>. If one argument is given,
<meth>callcc</meth> returns it. Otherwise, an array containing
<obj>args</obj> is returned.
<p/>
<codefragment>
<fullcode><![CDATA[ callcc {|cont| cont.call }
callcc {|cont| cont.call 1 }
callcc {|cont| cont.call 1, 2, 3 }
]]></fullcode><rubycode>
<tr>
<td><tt>callcc<nbsp/>{|cont|<nbsp/><nbsp/>cont.call<nbsp/>}</tt></td>
<td>»</td>
<td><tt>nil</tt></td>
</tr>
<tr>
<td><tt>callcc<nbsp/>{|cont|<nbsp/><nbsp/>cont.call<nbsp/>1<nbsp/>}</tt></td>
<td>»</td>
<td><tt>1</tt></td>
</tr>
<tr>
<td><tt>callcc<nbsp/>{|cont|<nbsp/><nbsp/>cont.call<nbsp/>1,<nbsp/>2,<nbsp/>3<nbsp/>}</tt></td>
<td>»</td>
<td><tt>[1,<nbsp/>2,<nbsp/>3]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
</desc>
</method>
<p/>
</methods>
<p/>
</class>
</ppdoc>
|