<br><br><div class="gmail_quote">On Wed, Nov 2, 2011 at 1:15 PM, Igor Stasenko <span dir="ltr">&lt;<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>&gt;</span> wrote:<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>
On 2 November 2011 20:55, Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; On Wed, Nov 2, 2011 at 11:33 AM, Levente Uzonyi &lt;<a href="mailto:leves@elte.hu">leves@elte.hu</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On Wed, 2 Nov 2011, Igor Stasenko wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt; Here the original implementation, which Array inherits from<br>
&gt;&gt;&gt; SequenceableCollection:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; at: index ifAbsent: exceptionBlock<br>
&gt;&gt;&gt;        &quot;Answer the element at my position index. If I do not contain an element<br>
&gt;&gt;&gt;        at index, answer the result of evaluating the argument, exceptionBlock.&quot;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;        (index between: 1 and: self size) ifTrue: [^ self at: index].<br>
&gt;&gt;&gt;        ^ exceptionBlock value<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; the thing is, that #at: primivite also doing a range checking and<br>
&gt;&gt;&gt; fails if index is invalid, so if index is valid, as result we<br>
&gt;&gt;&gt; performing a range checking twice instead of just once.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Here the simple implementation how to make things faster:<br>
&gt;&gt;&gt; fat: index<br>
&gt;&gt;&gt;        &quot;Primitive. Assumes receiver is indexable. Answer the value of an<br>
&gt;&gt;&gt;        indexable element in the receiver. Fail if the argument index is not an<br>
&gt;&gt;&gt;        Integer or is out of bounds. Essential. See Object documentation<br>
&gt;&gt;&gt;        whatIsAPrimitive. Read the class comment for a discussion about that the fact<br>
&gt;&gt;&gt;        that the index can be a float.&quot;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;        &lt;primitive: 60&gt;<br>
&gt;&gt;&gt;        ^ #plopp<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; fat: index ifAbsent: aBlock<br>
&gt;&gt;&gt;        | x |<br>
&gt;&gt;&gt;        x := (self fat: index).<br>
&gt;&gt;&gt;        x == #plopp ifTrue: [ ^ aBlock value ].<br>
&gt;&gt;&gt;        ^ x<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; And speedup is almost 2 times:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; [ 1000000 timesRepeat: [ #(1 2 4 5 56 67 67) at: 1 ifAbsent: nil ] ] timeToRun<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; 39<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; [ 1000000 timesRepeat: [ #(1 2 4 5 56 67 67) at: 1 ifAbsent: nil ] ] timeToRun<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; 20<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Even when index is out of range, it is still much faster:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; [ 1000000 timesRepeat: [ #(1 2 4 5 56 67 67) at: 100 ifAbsent: nil ] ] timeToRun<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; 35<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; [ 1000000 timesRepeat: [ #(1 2 4 5 56 67 67) fat: 100 ifAbsent: nil ]<br>
&gt;&gt;&gt; ] timeToRun<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; 24<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The problem, of course, that trick with #plopp is a dirty hack.<br>
&gt;&gt;&gt; Because if array include an #plopp object as element, it will report<br>
&gt;&gt;&gt; as it absent,<br>
&gt;&gt;&gt; instead of answering it.<br>
&gt;&gt;&gt; There is no way to ensure that any arbitrary object are never included<br>
&gt;&gt;&gt; as element in array, so this is no-go for generic replacement.<br>
&gt;&gt;&gt; But in controlled environment, when you know that none of arrays which<br>
&gt;&gt;&gt; you using with #fat:ifAbsent: will ever include #plopp (or pick your<br>
&gt;&gt;&gt; own unique object)<br>
&gt;&gt;&gt; it may be a good alternative.<br>
&gt;&gt;<br>
&gt;&gt; I&#39;ve been thinking about this earlier and there&#39;s a much nicer and simpler solution, though it requires vm changes :). The idea is to change primitive 60 to work for 2 parameters too, so #at:ifAbsent: could also use the primitive directly. There were a few changes about #at: recently (mirror prims, cog), so I&#39;m not sure it&#39;s still easy to change the primitive.<br>

&gt;<br>
&gt; his is neat, but it wouldn&#39;t be an extension to primitive 60 but a new primitive that would ignore its top of stack.  primitive 60 can operate with 2 args,when used as a mirror primitive,  but then it ignores the receiver.  Your usage would ignore the last argument.<br>

&gt; So choose a primitive number and I&#39;ll make it so...<br>
<br>
</div></div>Of course i was thinking about changing VM too. But i am uncertain if<br>
it worth doing so, because maybe this is too low reward for putting<br>
effort in it.<br>
<br>
But if we going to make new prim , here&#39;s what i&#39;d like to have<br>
 - use proper prim error code(s) to distinguish between cases:<br>
   - a receiver is not indexable/variable object<br>
   - an index is integer, but points outside of array&#39;s range<br>
   - an object passed as index is non-integer<br></blockquote><div><br></div><div>I agree.  I was going to brag that the Cog VM already has this implemented but the error code returned for a non-indexable receiver is wrong.  It should be #&#39;bad receiver&#39; but the prim always answers #&#39;bad index&#39;.  I&#39;ll fix this.  Primitive error codes and relevant usage in primitives still need to be ported to the standard VM though.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
this is to eliminate code which tries to guess what is really happen:<br>
<br>
&lt;primitive: 60&gt;<br>
index isInteger ifTrue:<br>
                [self class isVariable<br>
                        ifTrue: [self errorSubscriptBounds: index]<br>
                        ifFalse: [self errorNotIndexable]].<br>
        index isNumber<br>
                ifTrue: [^self at: index asInteger]<br>
                ifFalse: [self errorNonIntegerIndex]<br>
<br>
<br>
Btw, this is an example of how much more flexibility we could earn, if<br>
we could rewrite basic prims to count (and use) arguments from bottom<br>
of stack (receiver) instead from top,<br>
so primitives could be used in more flexible manner.<br>
<div><div></div><div class="h5"><br>
<br>
--<br>
Best regards,<br>
Igor Stasenko.<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>