<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>def Tenako.blog () end &#187; stack</title>
	<atom:link href="http://blog.tenako.com/tag/stack/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tenako.com</link>
	<description></description>
	<lastBuildDate>Sun, 10 Jul 2011 10:15:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Ruby: callcc</title>
		<link>http://blog.tenako.com/2009/06/03/ruby-callc/</link>
		<comments>http://blog.tenako.com/2009/06/03/ruby-callc/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 15:04:00 +0000</pubDate>
		<dc:creator>farruco</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[callcc]]></category>
		<category><![CDATA[continuations]]></category>
		<category><![CDATA[frame]]></category>
		<category><![CDATA[stack]]></category>

		<guid isPermaLink="false">http://blog.tenako.com/?p=160</guid>
		<description><![CDATA[callcc, es la abreviatura de call-with-current-continuation, algo así como un goto con esteroides. En el rdoc nos encontramos con la siguiente definición: callcc &#123;&#124;cont&#124; block &#125; =&#62; obj Generates a Continuation object, which it passes to the associated block. Performing a cont.call will cause the callcc to return (as will falling through the end of [...]]]></description>
			<content:encoded><![CDATA[<p><strong>callcc</strong>, es la abreviatura de call-with-current-continuation, algo así como un goto con esteroides.</p>
<p>En el <a href="http://www.ruby-doc.org/core/classes/Kernel.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.ruby-doc.org');" target="_blank">rdoc</a> nos encontramos con la siguiente definición:</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">callcc <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>cont<span style="color:#006600; font-weight:bold;">|</span> block <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> obj</pre></div></div>

<p>Generates a Continuation object, which it passes to the associated block. Performing a cont.call will cause the callcc to return (as will falling through the end of the block). The value returned by the callcc is the value of the block, or the value passed to cont.call. See class Continuation for more details. Also see Kernel::throw for an alternative mechanism for unwinding a call stack.
</p></blockquote>
<p>Un tanto críptico, ¿No?. Basicamente, callcc almacena la dirección de memoria y el contexto  (en un objeto <a href="http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_continuation.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.ruby-doc.org');" target="_blank">Continuation</a>) de donde se le llamo. Sigue siendo raro,¿No?</p>
<p>Mejor un ejemplo. Sea el siguiente metodo:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">&nbsp;
counter = <span style="color:#006666;">0</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> foo
<span style="color:#CC0066; font-weight:bold;">exit</span> <span style="color:#9966CC; font-weight:bold;">if</span> callcc<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>$cont<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#006600; font-weight:bold;">&#125;</span> == <span style="color:#006666;">3</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;hello world&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
foo
&nbsp;
<span style="color:#ff6633; font-weight:bold;">$cont</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>counter <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>(Si ya se que las variables globales son malignas : ( )</p>
<p>Ejecutando el ejemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">madtrick::madtrick::<span style="color: #007800;">$ruby</span> test3.rb
hello world
hello world
hello world</pre></div></div>

<p>Como se puede apreciar, se imprimen tres &#8220;hello world&#8221; con sólo una llamada al método foo. </p>
<p>¿Qué podemos extraer del ejemplo anterior?</p>
<ul>
<li> Cada llamada a la continuación ($cont) nos vuelve a llevar a linea donde se definió.</li>
<li> Si en la llamada a la continuación pasamos algun parámetro, este es devuelto por callcc</li>
</ul>
<p>Tambien podríamos utilizar los ejemplos del post anterior (<a href="http://blog.tenako.com/2009/06/01/ruby-tco-tail-call-optimization/"  target="_blank">Tail Call Optimization</a>) para explicar el funcionamiento de callcc:</p>
<p>Calculo del factorial de un número:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> TCOTest
  <span style="color:#008000; font-style:italic;"># tail-recursive factorial</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> fact<span style="color:#006600; font-weight:bold;">&#40;</span> n, acc = <span style="color:#006666;">1</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> n <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006666;">2</span> <span style="color:#9966CC; font-weight:bold;">then</span>
      acc
    <span style="color:#9966CC; font-weight:bold;">else</span>
       fact<span style="color:#006600; font-weight:bold;">&#40;</span> n<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span>, n<span style="color:#006600; font-weight:bold;">*</span>acc <span style="color:#006600; font-weight:bold;">&#41;</span> 
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> fact_cc<span style="color:#006600; font-weight:bold;">&#40;</span> n, acc = <span style="color:#006666;">1</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    cont = callcc<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>cont<span style="color:#006600; font-weight:bold;">|</span> cont<span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> n <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006666;">2</span> <span style="color:#9966CC; font-weight:bold;">then</span>
      acc
    <span style="color:#9966CC; font-weight:bold;">else</span>
       n, acc = n<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span>, n<span style="color:#006600; font-weight:bold;">*</span>acc
       cont.<span style="color:#9900CC;">call</span> cont 
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># length of factorial</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> fact_size<span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>
    fact<span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">size</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    $!
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
&nbsp;
  <span style="color:#008000; font-style:italic;"># length of factorial</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> fact_size_cc<span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>
    fact_cc<span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">size</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    $!
  <span style="color:#9966CC; font-weight:bold;">end</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Si lo probamos en el irb vemos que fact_size_cc no da ningún tipo de problema mientras que la función fact_size (sí, por carecer Ruby de TCO) ya que nos quedamos sin espacio en la stack.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">...
irb<span style="color: #7a0874; font-weight: bold;">&#40;</span>main<span style="color: #7a0874; font-weight: bold;">&#41;</span>:009:<span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">&gt;</span> t.fact_size <span style="color: #000000;">10000</span>
=<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #666666; font-style: italic;">#&lt;SystemStackError: stack level too deep&gt;</span>
irb<span style="color: #7a0874; font-weight: bold;">&#40;</span>main<span style="color: #7a0874; font-weight: bold;">&#41;</span>:010:<span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">&gt;</span> t.fact_size_cc <span style="color: #000000;">10000</span>
=<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000;">14808</span></pre></div></div>

<p>El otro ejemplo del post anterior, la función de Fibonacci:</p>
<p>En el ejemplo anterior, utilizábamos la palabra reservada <strong>redo</strong> junto con  un método definido ad-hoc para poder realizar el cálculo:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  define_method<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:acc</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>i, n, result<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> i == <span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span>
      result
    <span style="color:#9966CC; font-weight:bold;">else</span>
      i, n, result = i <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#006666;">1</span>, n <span style="color:#006600; font-weight:bold;">+</span> result, n
      <span style="color:#9966CC; font-weight:bold;">redo</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> fib_redo<span style="color:#006600; font-weight:bold;">&#40;</span>i<span style="color:#006600; font-weight:bold;">&#41;</span>
   acc i,<span style="color:#006666;">1</span>,<span style="color:#006666;">0</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Pero tambien se podria haber hecho de esta otra forma:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> fib_call_cc<span style="color:#006600; font-weight:bold;">&#40;</span>i, n = <span style="color:#006666;">1</span>, result = <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  cont = callcc<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>cont<span style="color:#006600; font-weight:bold;">|</span> cont<span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> i == <span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span>
    result
  <span style="color:#9966CC; font-weight:bold;">else</span>
    i, n, result = i <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#006666;">1</span>, n <span style="color:#006600; font-weight:bold;">+</span> result, n
    cont.<span style="color:#9900CC;">call</span> cont
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En el ejemplo anterior se puede apreciar como el contexto se mantiene. En este caso para los valores <strong>i</strong>,<strong>n</strong> y <strong>result</strong>.</p>
<p>Si ejecutamos un simple benchmark (para n en 50000) para comparar redo vs callcc, obtenemos los siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">&nbsp;
madtrick::madtrick::<span style="color: #007800;">$ruby</span> test.rb 
Time <span style="color: #000000; font-weight: bold;">for</span> fib_redo:      <span style="color: #000000;">0.390000</span>   <span style="color: #000000;">0.010000</span>   <span style="color: #000000;">0.400000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>  <span style="color: #000000;">0.403986</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time <span style="color: #000000; font-weight: bold;">for</span> fib_call_cc:   <span style="color: #000000;">0.500000</span>   <span style="color: #000000;">0.000000</span>   <span style="color: #000000;">0.500000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>  <span style="color: #000000;">0.519504</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>redo (  0.403986) es un poco más rápido que callcc (  0.519504). Echándole un vistazo rapido al codigo de la máquina virtual de Ruby se entiende rápidamente el porque. <strong>redo</strong> esta implentado utilizando goto&#8217;s mientras que callcc es una llamada a una función que se encarga de guardar toda la información necesaria en un objeto Continuation, por lo que necesita más tiempo.</p>
<p>Para mas información sobre callcc, su funcionamiento y los continuations:</p>
<ul>
<li><a href="http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.intertwingly.net');">Continuations</a></li>
<li><a href="http://www.madore.org/~david/computers/callcc.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.madore.org');">Callcc</a></li>
<li><a href="http://www.cs.utk.edu/~huangj/cs360/360/notes/Setjmp/lecture.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.cs.utk.edu');">Setjmp/longjmp</a>, funciones en C con las que se puede implementar un comportamiento similar</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.tenako.com/2009/06/03/ruby-callc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

