Hi Juan,<br><br><div class="gmail_quote">On Tue, Nov 2, 2010 at 2:35 PM, Juan Vuletich <span dir="ltr"><<a href="mailto:juan@jvuletich.org">juan@jvuletich.org</a>></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 <<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a> <mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a>>> wrote:<br>
<br>
Eliot Miranda wrote:<br>
<br>
<br>
<br>
On Tue, Nov 2, 2010 at 1:23 PM, Juan Vuletich<br>
<<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a> <mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a>><br></div><div><div></div><div class="h5">
<mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a> <mailto:<a href="mailto:juan@jvuletich.org" target="_blank">juan@jvuletich.org</a>>>> wrote:<br>
<br>
Nicolas Cellier wrote:<br>
<br>
<br>
I'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't include any of them yet. I can add whatever people<br>
prefer. What I'd do different is the implementation:<br>
<br>
fold: aBinaryBlock<br>
<br>
"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."<br>
"<br>
#('if' 'it' 'is' 'to' 'be' 'it' 'is' 'up' 'to' 'me')<br>
fold: [:a<br>
:b | a, ' ', b]<br>
"<br>
| noPreviousValue |<br>
noPreviousValue := Object new. "something that can't be in<br>
the receiver"<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'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'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'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: [#('if' 'it' 'is' 'to' 'be' 'it' 'is' 'up'<br>
'to' 'me') fold: [:a :b | a, ' ', b]]] timeToRun 2710 | 879<br>
[100000 timesRepeat: [#('if' 'it' 'is' 'to' 'be' 'it' 'is' 'up'<br>
'to' 'me') foldx: [:a :b | a, ' ', b]]] timeToRun 2723 | 874<br>
[100000 timesRepeat: [#('if' 'it' 'is' 'to' 'be' 'it' 'is' 'up'<br>
'to' 'me') reduce: [:a :b | a, ' ', b]]] timeToRun 2780 | 881<br>
<br>
<br>
Be very careful to run these under the same conditions. You'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 & allocation and focus more on the costs of the various fold: implementations.<br>
</div></div></blockquote>
<br>
You'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't need assignment to outer temps, and I see that<br>
'cleaner' and closer to FP.<br>
<br>
<br>
<br>
But the assignment to the outer temp is hidden in inject:into:; it's still there ;)<br>
</blockquote>
<br>
:)<br>
<br>
Cheers,<br>
Juan Vuletich<br>
<br>
</div></div></blockquote></div><br>