<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>Hi Levente,</p>
<p><br>
</p>
<p>alright, I'll try to measure and optimize them again.</p>
<p><br>
</p>
<p>> <span style="font-size:12pt">Two things I saw and you didn't mention are block creation</span><span style="font-size:12pt"></span></p>
<div><br>
</div>
<div>You mean that "ifNone: [0]"? One could replace it with "ifNone: 0" to avoid duplication.</div>
<div><br>
</div>
<div>> <span>and introduction of non-jittable comparison.</span></div>
<div><span><br>
</span></div>
<div><span>What are you referring to?</span></div>
<div><span><br>
</span></div>
<div><span>Best,</span></div>
<div><span>Christoph</span></div>
<p></p>
<div id="x_Signature">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:rgb(0,0,0); font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div name="x_divtagdefaultwrapper" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:; margin:0">
<div><font size="2" color="#808080"></font></div>
</div>
</div>
</div>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves@caesar.elte.hu><br>
<b>Gesendet:</b> Montag, 17. Februar 2020 01:00:11<br>
<b>An:</b> The general-purpose Squeak developers list<br>
<b>Betreff:</b> Re: [squeak-dev] The Inbox: Collections-ct.875.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Hi Christoph,<br>
<br>
On Sun, 16 Feb 2020, Thiede, Christoph wrote:<br>
<br>
> <br>
> Hi Levente,<br>
> <br>
> <br>
> thanks for the suggestions.<br>
> <br>
> <br>
> > And one more thing: These method resemble #indexOf:* methods, so I think #ifAbsent: is a better choice than #ifNone:.<br>
> <br>
> <br>
> Agreed :-)<br>
> <br>
> > I suggest keeping the all method comments<br>
> <br>
> Personally, I see little value in documenting a one-liner. Documentation is useful for explaining and optimized method that does not provide the typical Smalltalk readability. Plus, they all need to be maintained ...<br>
<br>
If one sees #findLast: being sent somewhere, and one doesn't know what it <br>
does, with your changes, it means looking up the implementors three times <br>
to get to the actual implementation and comment.<br>
<br>
> <br>
> > measuring the performance impact of the rewrite.<br>
> <br>
> What is the critical point here?<br>
> Of course, the stack will be a little higher, but the asymptotic cost does not change. We only evaluate anotherBlock at the end instead of returning 0.<br>
<br>
Two things I saw and you didn't mention are block creation and <br>
introduction of non-jittable comparison.<br>
<br>
> <br>
> Please do not misunderstand me: I honor optimizing critical Smalltalk methods, but I always strive to avoid premature optimization.<br>
<br>
In my opinion, generic library methods like these should be optimized by <br>
definition.<br>
<br>
Calling premature optimization means that you assume that if these methods <br>
were written in a more optimal way, then their complexity and/or <br>
legibility would be worse.<br>
Have a look at #indexOf:*, and you'll see that's not the case.<br>
<br>
> Should we maybe establish to practice to store such benchmarks somewhere in the trunk so that not every willing contributor needs to write them again?<br>
<br>
I think methods like these don't change often enough (presumably they <br>
never change) to justify storing benchmarks for them.<br>
<br>
<br>
Levente<br>
<br>
> <br>
> Best,<br>
> Christoph<br>
> <br>
> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________<br>
> Von: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves@caesar.elte.hu><br>
> Gesendet: Sonntag, 16. Februar 2020 22:47:10<br>
> An: The general-purpose Squeak developers list<br>
> Betreff: Re: [squeak-dev] The Inbox: Collections-ct.875.mcz  <br>
> And one more thing: These method resemble #indexOf:* methods, so I think<br>
> #ifAbsent: is a better choice than #ifNone:.<br>
> <br>
> Levente<br>
> <br>
> On Sun, 16 Feb 2020, Levente Uzonyi wrote:<br>
> <br>
> > Hi Christoph,<br>
> ><br>
> > I suggest keeping the all method comments, and measuring the performance<br>
> > impact of the rewrite.<br>
> ><br>
> > Levente<br>
> ><br>
> > On Sun, 16 Feb 2020, commits@source.squeak.org wrote:<br>
> ><br>
> >> A new version of Collections was added to project The Inbox:<br>
> >> <a href="http://source.squeak.org/inbox/Collections-ct.875.mcz">http://source.squeak.org/inbox/Collections-ct.875.mcz</a><br>
> >><br>
> >> ==================== Summary ====================<br>
> >><br>
> >> Name: Collections-ct.875<br>
> >> Author: ct<br>
> >> Time: 16 February 2020, 3:32:23.116 pm<br>
> >> UUID: 61ea773b-1408-c040-a712-09238ee6fe2f<br>
> >> Ancestors: Collections-topa.873<br>
> >><br>
> >> Extends and realigns version of #findFirst: and #findLast:.<br>
> >><br>
> >> =============== Diff against Collections-topa.873 ===============<br>
> >><br>
> >> Item was changed:<br>
> >>  ----- Method: SequenceableCollection>>findFirst: (in category<br>
> > 'enumerating') -----<br>
> >>  findFirst: aBlock<br>
> >> -     "Return the index of my first element for which aBlock evaluates as<br>
> > true."<br>
> >><br>
> >> +     ^ self findFirst: aBlock startingAt: 1!<br>
> >> -     | index |<br>
> >> -     index := 0.<br>
> >> -     [(index := index + 1) <= self size] whileTrue:<br>
> >> -             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> >> -     ^ 0!<br>
> >><br>
> >> Item was added:<br>
> >> + ----- Method: SequenceableCollection>>findFirst:ifNone: (in category<br>
> > 'enumerating') -----<br>
> >> + findFirst: aBlock ifNone: anotherBlock<br>
> >> +<br>
> >> +     ^ self findFirst: aBlock startingAt: 1 ifNone: anotherBlock!<br>
> >><br>
> >> Item was added:<br>
> >> + ----- Method: SequenceableCollection>>findFirst:startingAt: (in category<br>
> > 'enumerating') -----<br>
> >> + findFirst: aBlock startingAt: minIndex<br>
> >> +<br>
> >> +     ^ self findFirst: aBlock startingAt: minIndex ifNone: [0]!<br>
> >><br>
> >> Item was added:<br>
> >> + ----- Method: SequenceableCollection>>findFirst:startingAt:ifNone: (in<br>
> > category 'enumerating') -----<br>
> >> + findFirst: aBlock startingAt: minIndex ifNone: anotherBlock<br>
> >> +     "Return the index of my first element with index >= minIndex for<br>
> > which aBlock evaluates as true. If no element is found, return the value of<br>
> > anotherBlock."<br>
> >> +<br>
> >> +     | index |<br>
> >> +     index := minIndex - 1.<br>
> >> +     [(index := index + 1) <= self size] whileTrue:<br>
> >> +             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> >> +     ^ anotherBlock value!<br>
> >><br>
> >> Item was changed:<br>
> >>  ----- Method: SequenceableCollection>>findLast: (in category<br>
> > 'enumerating') -----<br>
> >>  findLast: aBlock<br>
> >> -     "Return the index of my last element for which aBlock evaluates as<br>
> > true."<br>
> >><br>
> >> +     ^ self findLast: aBlock startingAt: 1!<br>
> >> -     | index |<br>
> >> -     index := self size + 1.<br>
> >> -     [(index := index - 1) >= 1] whileTrue:<br>
> >> -             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> >> -     ^ 0!<br>
> >><br>
> >> Item was added:<br>
> >> + ----- Method: SequenceableCollection>>findLast:ifNone: (in category<br>
> > 'enumerating') -----<br>
> >> + findLast: aBlock ifNone: anotherBlock<br>
> >> +<br>
> >> +     ^ self findLast: aBlock startingAt: 1 ifNone: anotherBlock!<br>
> >><br>
> >> Item was changed:<br>
> >>  ----- Method: SequenceableCollection>>findLast:startingAt: (in category<br>
> > 'enumerating') -----<br>
> >> + findLast: aBlock startingAt: minIndex<br>
> >> - findLast: aBlock startingAt: i<br>
> >> -     "Return the index of my last element with index >= i for which aBlock<br>
> > evaluates as true."<br>
> >><br>
> >> +     ^ self findLast: aBlock startingAt: minIndex ifNone: [0]!<br>
> >> -     | index |<br>
> >> -     index := self size + 1.<br>
> >> -     [(index := index - 1) >= i] whileTrue:<br>
> >> -             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> >> -     ^ 0!<br>
> >><br>
> >> Item was added:<br>
> >> + ----- Method: SequenceableCollection>>findLast:startingAt:ifNone: (in<br>
> > category 'enumerating') -----<br>
> >> + findLast: aBlock startingAt: minIndex ifNone: anotherBlock<br>
> >> +     "Return the index of my last element with index >= minIndex for which<br>
> > aBlock evaluates as true.  If no element is found, return the value of<br>
> > anotherBlock."<br>
> >> +<br>
> >> +     | index |<br>
> >> +     index := self size + 1.<br>
> >> +     [(index := index - 1) >= minIndex] whileTrue:<br>
> >> +             [(aBlock value: (self at: index)) ifTrue: [^index]].<br>
> >> +     ^ anotherBlock value!<br>
> ><br>
> ><br>
> <br>
> <br>
></div>
</span></font>
</body>
</html>