Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
320 lines (218 sloc) 7.84 KB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>The TriBase RoR course</title>
<!-- metadata -->
<meta name="generator" content="S5" />
<meta name="version" content="S5 1.1" />
<meta name="presdate" content="20050728" />
<meta name="author" content="Jonathan Gross" />
<meta name="company" content="BiolData ltd." />
<!-- configuration parameters -->
<meta name="defaultView" content="slideshow" />
<meta name="controlVis" content="hidden" />
<!-- style sheet links -->
<link rel="stylesheet" href="../ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
<link rel="stylesheet" href="../ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
<link rel="stylesheet" href="../lib/stylesheets/print.css" type="text/css" media="print" id="slidePrint" />
<link rel="stylesheet" href="../ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
<link rel="stylesheet" href="../lib/stylesheets/pressie.css" type="text/css" />
<!-- S5 JS -->
<script src="../ui/default/slides.js" type="text/javascript"></script>
<!-- Syntax Highlighter -->
<link rel="stylesheet" href="../dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css"></link>
</head>
<body>
<div class="layout">
<div id="controls"><!-- DO NOT EDIT --></div>
<div id="currentSlide"><!-- DO NOT EDIT --></div>
<div id="header"></div>
<div id="footer">
<h2>Copyright &copy; 2008 Jonathan Gross</h2>
</div>
</div>
<div class="presentation">
<div class="slide">
<h1>An Example</h1>
<p>This comes from the <a href="http://pragmaticstudio.com/ruby/">Advanced Ruby Course</a></p>
</div>
<div class="slide">
<h1>Continuation</h1>
<div style="width: 50%; float: right">
<div class="code-normal">
<pre name="code" class="ruby:nogutter:nocontrols">def open_box(continuation)
continuation.call if rand &lt; 0.5
end
callcc do |continuation|
puts "opening box"
open_box(continuation)
puts "Phew--kitty's OK"
end
puts "closing box"</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/basic_continuation.rb">code/control/basic_continuation.rb</a></div>
</div>
<div style="width: 50%">
<ul>
<li>Construct using <code>callcc</code>
<ul>
<li>pass it a block</li>
<li>block receives <code>Continuation</code> object</li>
<li>invoke that object&#8217;s <code>call</code> method, and control passes to the end of that block</li>
</ul></li>
</ul>
</div>
</div>
<div class="slide">
<h1>Continuations Are Closures</h1>
<div class="code-normal">
<pre name="code" class="ruby:nogutter:nocontrols">def create_continuation(arg)
callcc { |continuation| return continuation }
puts "Back in method: arg = #{arg}"
exit
end
cont_one = create_continuation(123)
cont_one.call #=&gt; Back in method: arg = 123</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/closure_continuation.rb">code/control/closure_continuation.rb</a></div>
</div>
<div class="slide">
<h1>But&#8230;</h1>
<div class="code-normal">
<pre name="code" class="ruby:nogutter:nocontrols">def create_continuation(arg)
callcc { |continuation| return continuation }
puts "Back in method: arg = #{arg}"
end
cont_one = create_continuation(123)
cont_one.call
### Results in:
#
# Back in method: arg = 123
# closure_continuation_2.rb:8: undefined method `call' for nil:NilClass
</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/closure_continuation_2.rb">code/control/closure_continuation_2.rb</a></div>
</div>
<div class="slide">
<h1>But&#8230;</h1>
<div>
<div class="code-normal">
<pre name="code" class="ruby:nogutter:nocontrols">def create_continuation(arg)
callcc { |continuation| return continuation }
puts "Back in method: arg = #{arg}"
end
cont_one = create_continuation(123)
cont_one.call
### Results in:
#
# Back in method: arg = 123
# closure_continuation_2.rb:8: undefined method `call' for nil:NilClass
</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/closure_continuation_2.rb">code/control/closure_continuation_2.rb</a></div>
<div style="position: relative; left: 60%; top: -3em; font-size: 400%; color: #6b6">Why?</div>
</div>
</div>
<div class="slide">
<h1>Implementing throw&#8230;catch</h1>
<p>Let&#8217;s try to implement throw and catch so that the following works as expected:</p>
<div class="code-normal">
<pre name="code" class="ruby:nogutter:nocontrols">def test_method
CC.throw(:x, "thrown X") if rand &lt; 0.5
end
result = CC.catch(:x) do
test_method
"normal exit"
end
puts "Result is #{result}"
</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/cc_throw_catch.rb">code/control/cc_throw_catch.rb</a></div>
</div>
<div class="slide">
<h1>Implementing throw&#8230;catch</h1>
<ul>
<li>We need a thread-local stack of all current catch blocks</li>
</ul>
<ul>
<li>When we see a <code>catch</code>, we store the symbol and a continuation for the block on the stack. If that continuation gets called, execution resumes after the block (which is what <code>catch</code> does)</li>
</ul>
<ul>
<li>When we see a <code>throw</code> we traverse it looking for the entry
with the corresponding system.</li>
</ul>
<ul>
<li>When we find that entry, we call the corresponding continuation</li>
</ul>
<p>&nbsp;</p>
<blockquote>
<p style="font-size="50%";">This implementation is based on code from Jim Weirich</p>
</blockquote>
</div>
<div class="slide">
<h1>Catch and Throw</h1>
<div class="code-tiny">
<pre name="code" class="ruby:nogutter:nocontrols">module CC
CATCH_STACK = CatchStack.new
def self.catch(sym)
callcc do |cc|
CATCH_STACK.wrap(sym, cc) do
yield
end
end
end
def self.throw(sym, value=nil)
cc = CATCH_STACK.find_continuation_for(sym)
cc.call(value)
end
end
</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/cc_throw_catch.rb">code/control/cc_throw_catch.rb</a></div>
</div>
<div class="slide">
<h1>And the stack</h1>
<div class="code-tiny">
<pre name="code" class="ruby:nogutter:nocontrols">class CatchStack
Frame = Struct.new(:symbol, :cc)
def stack
Thread.current[:catch_stack] ||= []
end
def wrap(symbol, cc)
stack &lt;&lt; Frame.new(symbol, cc)
begin
yield
ensure
stack.pop
end
end
def find_continuation_for(symbol)
stack.pop until stack.empty? || stack.last.symbol == symbol
if stack.empty?
fail NameError, "uncaught throw `#{sym}'"
else
stack.pop.cc
end
end
end
</pre></div><div class="codeurl"><a href="txmt://open?url=file:///DEVELOPMENT/git/codex_Ror/code/control/cc_throw_catch.rb">code/control/cc_throw_catch.rb</a></div>
</div>
<div class="slide">
<h1>Continuations.</h1>
<ul>
<li>Can&#8217;t invoke across threads</li>
</ul>
<ul>
<li>Can carry stale state around with them</li>
</ul>
<ul>
<li>Can use up a lot of memory</li>
</ul>
<ul>
<li>Are not fun to debug</li>
</ul>
<p>But&#8230;</p>
<ul>
<li>They&#8217;ll impress your friends</div></li>
</ul>
<!-- Syntax Highlighter -->
<script language="javascript" src="../dp.SyntaxHighlighter/Scripts/shCore.js"></script>
<script language="javascript" src="../dp.SyntaxHighlighter/Scripts/shBrushCpp.js"></script>
<script language="javascript" src="../dp.SyntaxHighlighter/Scripts/shBrushRuby.js"></script>
<script language="javascript" src="../dp.SyntaxHighlighter/Scripts/shBrushXml.js"></script>
<script language="javascript">
dp.SyntaxHighlighter.ClipboardSwf = '/flash/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
</script>
</div>
</body>
</html>