Hi Juan,<br><br><div class="gmail_quote">On Tue, Nov 2, 2010 at 2:35 PM, Juan Vuletich <span dir="ltr">&lt;<a href="mailto:juan@jvuletich.org">juan@jvuletich.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Eliot Miranda wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">
<br>
<br>
On Tue, Nov 2, 2010 at 1:50 PM, Juan Vuletich &lt;<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a> &lt;mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a>&gt;&gt; wrote:<br>

<br>
    Eliot Miranda wrote:<br>
<br>
<br>
<br>
        On Tue, Nov 2, 2010 at 1:23 PM, Juan Vuletich<br>
        &lt;<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a> &lt;mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a>&gt;<br></div><div><div></div><div class="h5">
        &lt;mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a> &lt;mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a>&gt;&gt;&gt; wrote:<br>
<br>
           Nicolas Cellier wrote:<br>
<br>
<br>
               I&#39;d say which selector are implemented in Pharo and Cuis ?<br>
               We should better converge.<br>
<br>
               Nicolas<br>
               <br>
           Hi folks,<br>
<br>
           Cuis doesn&#39;t include any of them yet. I can add whatever people<br>
           prefer. What I&#39;d do different is the implementation:<br>
<br>
           fold: aBinaryBlock<br>
<br>
             &quot;Evaluate the block with the first two elements of the<br>
        receiver,<br>
              then with the result of the first evaluation and the<br>
        next element,<br>
              and so on.  Answer the result of the final evaluation.<br>
        If the<br>
           receiver<br>
              is empty, raise an error. If the receiver has a single<br>
        element,<br>
           answer<br>
              that element.&quot;<br>
             &quot;<br>
             #(&#39;if&#39; &#39;it&#39; &#39;is&#39; &#39;to&#39; &#39;be&#39; &#39;it&#39; &#39;is&#39; &#39;up&#39; &#39;to&#39; &#39;me&#39;)<br>
        fold: [:a<br>
           :b | a, &#39; &#39;, b]<br>
             &quot;<br>
             | noPreviousValue |<br>
             noPreviousValue := Object new.    &quot;something that can&#39;t be in<br>
           the receiver&quot;<br>
             ^self inject: noPreviousValue into: [ :previousValue :each |<br>
                 previousValue == noPreviousValue<br>
                     ifTrue: [ each ]<br>
                     ifFalse: [ aBinaryBlock value: previousValue<br>
        value: each ]]<br>
<br>
           This is easier to understand, and it also makes clear the<br>
        relation<br>
           between #fold: (or #reduce:) and #inject:into: .<br>
<br>
<br>
        I disagree.   inject:into: is not particularly easy to<br>
        understand, whereas both the existing fold: and reduce: are<br>
        understandable in terms of do:.<br>
<br>
<br>
    I say this is easier to understand, given that #inject:into: is<br>
    already understood. #inject:into: and #fold: / #reduce: are very<br>
    close in what they do. So close, that it is best to show how they<br>
    differ. That&#39;s what my implementation does. Showing the use of<br>
    #inject:into:  (with proper names for block args) is a didactic<br>
    bonus.<br>
<br>
<br>
        Also the use of inject:into: isn&#39;t really buying you anything<br>
        since the logic in the block within the inject:into: usage is<br>
        as complex as that within fold: or reduce:. Further, this /is/<br>
        a lot slower because of the extra level of evaluation (there&#39;s<br>
        an extra block activation around each element).<br>
<br>
                 best,<br>
        Eliot<br>
<br>
<br>
    No, it is not slower:<br>
      [100000 timesRepeat: [#(&#39;if&#39; &#39;it&#39; &#39;is&#39; &#39;to&#39; &#39;be&#39; &#39;it&#39; &#39;is&#39; &#39;up&#39;<br>
    &#39;to&#39; &#39;me&#39;) fold: [:a :b | a, &#39; &#39;, b]]] timeToRun 2710 | 879<br>
      [100000 timesRepeat: [#(&#39;if&#39; &#39;it&#39; &#39;is&#39; &#39;to&#39; &#39;be&#39; &#39;it&#39; &#39;is&#39; &#39;up&#39;<br>
    &#39;to&#39; &#39;me&#39;) foldx: [:a :b | a, &#39; &#39;, b]]] timeToRun 2723 | 874<br>
      [100000 timesRepeat: [#(&#39;if&#39; &#39;it&#39; &#39;is&#39; &#39;to&#39; &#39;be&#39; &#39;it&#39; &#39;is&#39; &#39;up&#39;<br>
    &#39;to&#39; &#39;me&#39;) reduce: [:a :b | a, &#39; &#39;, b]]] timeToRun 2780 | 881<br>
<br>
<br>
Be very careful to run these under the same conditions.  You&#39;d need to run each of these immediately following a GC to get meaningful results.  Also use 1 to: n do for the outer loop since timesRepeat: uses do: and so the measurement harness is probably a significant fraction of the run-time.  Also measure the single-element cost.  BTW, I would use (1 to: 10) fold: [:a :b| a + b] to reduce the overhead of string concatenation &amp; allocation and focus more on the costs of the various fold: implementations.<br>

</div></div></blockquote>
<br>
You&#39;re right wrt performance (only tried Cog on this example):<br>
   Smalltalk garbageCollect. [1 to: 200000 do: [ :i | (1 to: 100) fold: [:a :b| a + b] ]] timeToRun 1367<br>
   Smalltalk garbageCollect. [1 to: 200000 do: [ :i | (1 to: 100) foldx: [:a :b| a + b] ]] timeToRun 1656<br>
   Smalltalk garbageCollect. [1 to: 200000 do: [ :i | (1 to: 100) reduce: [:a :b| a + b] ]] timeToRun 1306</blockquote><div><br></div><div>Yes, alas one has to be hyper-careful.  For example if I run the following in my current image:</div>
<div><br></div><div>Smalltalk garbageCollect.</div><div>{ [1 to: 1000000 do: [ :i | (1 to: 100) fold: [:a :b| a + b] ]] timeToRun.</div>  [1 to: 1000000 do: [ :i | (1 to: 100) foldAlt: [:a :b| a + b] ]] timeToRun.<br>  [1 to: 1000000 do: [ :i | (1 to: 100) reduce: [:a :b| a + b] ]] timeToRun }</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">chances are that the second one will be fastest, irrespective of which implementation is used.  So change the order to foldAlt:, fold: reduce: and fold: will win, etc.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">Levente is very careful to measure the implementations precisely, so we can trust his numbers.</div><div class="gmail_quote"><br></div><div class="gmail_quote"><br>
</div><div class="gmail_quote">cheers,</div><div class="gmail_quote">Eliot<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div><div></div><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<br>
<br>
    #foldx: is my implementation. In all cases, the first number is<br>
    regular interpreter Squeak 4.2.4beta1U.app, the second number is<br>
    Cog Squeak 5.8b10-1.app on a 1.6GHz Mac mini.<br>
<br>
    The argument about complexity is more aesthetic than anything.<br>
<br>
<br>
Indeed; and so a matter of taste.  My aesthetics end up preferring fold: over the inject:into: based one :/<br>
<br>
 <br>
    My version doesn&#39;t need assignment to outer temps, and I see that<br>
    &#39;cleaner&#39; and closer to FP.<br>
<br>
<br>
<br>
But the assignment to the outer temp is hidden in inject:into:; it&#39;s still there ;)<br>
</blockquote>
<br>
:)<br>
<br>
Cheers,<br>
Juan Vuletich<br>
<br>
</div></div></blockquote></div><br>