<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le lun. 16 déc. 2019 à 16:54, Levente Uzonyi <<a href="mailto:leves@caesar.elte.hu">leves@caesar.elte.hu</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Mon, 16 Dec 2019, Thiede, Christoph wrote:<br>
<br>
> <br>
> Hi Tobias, thanks for your input!<br>
> <br>
> <br>
> > Why not simply<br>
> <br>
> >         Matrix rows: 5 columns: 6 tabulate: [:x :y | x @ y]<br>
> > <br>
> > What's wrong with blocks?<br>
> <br>
> At least in scripting scenarios, they cost extra redundant characters. Symbol >> #value:value: is a known selector (at least now), so why should I always type all these redundant letters?<br>
<br>
That's right. The sole advantage of having those methods is that they make <br>
writing scripts easier. IIRC, I asked here not to commit code into the <br>
Trunk using these "tricks". We can always use blocks, which are more <br>
legible for most smalltalkers, and they have better performance as well.<br>
<br></blockquote><div><br></div><div><div>I find evaluable Symbol very convenient and expressive enough.</div><div>(aCollection select: #odd)  , (aCollection collect: #squared) , (aCollection reduce: #+).</div><div><br></div><div>However, it's kind of abusing the purpose of Symbol class.</div><div>We should avoid a Frog class wanting to become bigger than an Ox class</div><div>(never mind, probably a joke for french <a href="https://fr.wikipedia.org/wiki/La_Grenouille_qui_se_veut_faire_aussi_grosse_que_le_b%C5%93uf">https://fr.wikipedia.org/wiki/La_Grenouille_qui_se_veut_faire_aussi_grosse_que_le_b%C5%93uf</a>)</div><div><br></div><div>We can cheat as long as we don't get caught, but with numArgs it sounds like we got caught...</div><div><br></div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> <br>
> > A symbol should not answer to an #value: … #value:value:...<br>
> Levente should know it, he implemented Symbol >> #value:value:.<br>
<br>
The goal with Symbol>>value:value: was to help writing sort blcoks, but <br>
now we have SortFunctions for that.<br>
The method follows the semantics of Symbol>>value:.<br>
Since sorting doesn't require more than two parameters, I didn't even <br>
consider adding further value:* variants.<br>
<br>
> However we solve this, I think, at the moment, we have an irritating inconsistency. Imho, Symbol >> #value: is not better than Symbol >> #value:value at all. And I use it every day, so I would vote for increasing the support.<br>
> (BalloonMorph allInstancesDo: #abandon, SystemWindow select: #isInWorld, ...)<br>
> <br>
> > I would then rather use withIndexCollect. It does what it says on the tin.<br>
> At the moment, we have #collect: and #withIndexCollect: side by side. However, their implementations are almost equal, and my problem is that every method that I write to access a collection (e. g. collection accessors) can<br>
> only support one of them. Why not exploit the fact that [:x :i | x + i] and [:x | x squared] can be distinguished by #numArgs and unify these two accessors?<br>
<br>
#numArgs is not suitable for that if you want to mix blocks with symbols. <br>
Creating a new method (e.g. I saw #arity in a VW discussion) would be a <br>
much better option.<br>
<br></blockquote><div><br></div><div>Since we got caught, we now require two different meanings indeed,</div><div>the number of arguments expected by the Symbol used as a selector</div><div>the number of arguments expected by the Symbol used as evaluable</div><div><br><div>The alternative would be to send a message for transforming a Symbol into an evaluable thing...</div><div>Like for SortFunction we can send (points sorted: #x ascending , #y descending)<br></div><div><br></div><div>I don't have good ones in mind, maybe something like (aCollection select: #odd asLambda)... Or #asBlock if we really want to compile a Block on the fly (that's an implementation detail IMO)...</div><div><br></div><div><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> <br>
> > you can use cull:cull: anyways.<br>
> Interesting point. This would also simplify the approaches for our recent #to:collect: issue:<br>
> (1 to: 5) collectX: [Color random]<br>
> <br>
> Could we maybe just adapt SequenceableCollection >> #collect: to support 0 - 2 block arguments instead of exactly one? It would be nice to have this in Trunk!<br>
> <br>
> > > Symbol >> #asBlock<br>
> > that's not too bad :D > but there is already perform:withArguments:, so this should be simpler?<br>
> <br>
> I would be glad to send something to the Inbox. But how do you create a block by reflection, without knowing the number of arguments?<br>
> It looks as if there is no public interface yet and I would have to generate the byte codes manually. Or am I overlooking something?<br>
<br>
That would be a cool feature, but it would make debugging a bit harder, <br>
because it would be hard to tell where those blocks come from.<br>
On the other hand, it could significantly speed up SortFunctions.<br>
<br></blockquote><div>If compiled once and used many, maybe.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
For collectX:, you don't need anything like that. Below is a simple and <br>
reasonably fast implementation. Note that it still has worse performance <br>
than #collect:.<br>
<br>
<br>
collectX: aValuable<br>
        "Evaluate aValuable with each of the receiver's elements and indices as optional arguments. Collect the resulting values into a collection like the receiver. Answer the new collection."<br>
<br>
        | index size newCollection |<br>
        newCollection := self species new: self size.<br>
        index := 0.<br>
        size := self size.<br>
        aValuable numArgs + (aValuable isSymbol ifTrue: [ 1 ] ifFalse: [ 0 ]) caseOf: {<br>
                [ 0 ] -> [<br>
                        [ (index := index + 1) <= size ] whileTrue: [<br>
                                newCollection at: index put: aValuable value ] ].<br>
                [ 1 ] -> [<br>
                        [ (index := index + 1) <= size ] whileTrue: [<br>
                                newCollection at: index put: (aValuable value: (self at: index)) ] ].<br>
                [ 2 ] -> [<br>
                        [ (index := index + 1) <= size ] whileTrue: [<br>
                                newCollection at: index put: (aValuable value: (self at: index) value: index) ] ] }.<br>
        ^newCollection<br>
<br></blockquote><div>I have always prefered seeing the other way arround, key first - value last like in keyAndValuesDo: rather than doWithIndex:</div><div>even though this does not lend itself to cull:cull:<br></div><div>And we could also create associations with (collection collectX: #->)<br><div>Otherwise we need <- like in the other thread :)</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Levente<br>
[1] <a href="http://forum.world.st/The-Trunk-Collections-ar-183-mcz-td481126.html" rel="noreferrer" target="_blank">http://forum.world.st/The-Trunk-Collections-ar-183-mcz-td481126.html</a><br>
<br>
P.S.: You may find these other discussions about this topic interesting:<br>
<a href="http://forum.world.st/Symbol-gt-gt-value-value-td1306944.html" rel="noreferrer" target="_blank">http://forum.world.st/Symbol-gt-gt-value-value-td1306944.html</a><br>
<a href="http://forum.world.st/Symbol-should-implement-cull-cull-td4758139.html" rel="noreferrer" target="_blank">http://forum.world.st/Symbol-should-implement-cull-cull-td4758139.html</a><br>
<a href="http://forum.world.st/Implementing-cull-cull-in-symbol-td4763781.html" rel="noreferrer" target="_blank">http://forum.world.st/Implementing-cull-cull-in-symbol-td4763781.html</a><br>
<a href="http://forum.world.st/Symbol-gt-value-td3778525.html" rel="noreferrer" target="_blank">http://forum.world.st/Symbol-gt-value-td3778525.html</a><br>
<a href="http://forum.world.st/Musing-on-Symbol-gt-gt-value-td3367942.html" rel="noreferrer" target="_blank">http://forum.world.st/Musing-on-Symbol-gt-gt-value-td3367942.html</a><br>
<br>
> <br>
> Best,<br>
> Christoph<br>
> <br>
> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________<br>
> Von: Squeak-dev <<a href="mailto:squeak-dev-bounces@lists.squeakfoundation.org" target="_blank">squeak-dev-bounces@lists.squeakfoundation.org</a>> im Auftrag von Tobias Pape <<a href="mailto:Das.Linux@gmx.de" target="_blank">Das.Linux@gmx.de</a>><br>
> Gesendet: Montag, 16. Dezember 2019 13:41:03<br>
> An: The general-purpose Squeak developers list<br>
> Betreff: Re: [squeak-dev] String >> #numArgs  <br>
> Hi<br>
> <br>
> > On 16.12.2019, at 13:18, Thiede, Christoph <<a href="mailto:Christoph.Thiede@student.hpi.uni-potsdam.de" target="_blank">Christoph.Thiede@student.hpi.uni-potsdam.de</a>> wrote:<br>
> ><br>
> > Hi all! :-)<br>
> ><br>
> > > Woah! This works? When and why is this useful? Does anybody recall the prime example? :-) #inject:into:?<br>
> ><br>
> > Yes, I believe I once used it with #inject:into:, but I don't remember. What prime example are you referring to? :)<br>
> > My personal favorite is:<br>
> > Matrix rows: 5 columns: 6 tabulate: #@ "for quickly setting up an example matrix :-)"<br>
> <br>
> Why not simply<br>
>         Matrix rows: 5 columns: 6 tabulate: [:x :y | x @ y]<br>
> <br>
> What's wrong with blocks?<br>
> <br>
> ><br>
> > I find it rather confusing that the following does not work:<br>
> > #raisedTo: value: 2 value: 3. "works"<br>
> > #raisedTo:modulo: value: 2 value: 3 value: 4. "does not understand"<br>
> > This is an inconsistency.<br>
> <br>
> Yes. The first case should also bail.<br>
> <br>
> A symbol answering to #perform: is IMHO borderline.<br>
> A symbol's answer to #value should be itself.<br>
> A symbol should not answer to an #value: … #value:value:...<br>
> <br>
> <br>
> ><br>
> > @Eliot:<br>
> > > Can you give some examples of where you find you are needing to do this?<br>
> ><br>
> > Actually, I was trying something like this:<br>
> > SequenceableCollection >> #collectX: aBlock<br>
> > ^ aBlock numArgs = 2<br>
> > ifTrue: [self withIndexCollect: aBlock]<br>
> > ifFalse: [self collect: aBlock]].<br>
> ><br>
> > Now you can say:<br>
> > #(1 2 3) collectX: [:x | x squared].<br>
> > #(1 2 3) collectX: #squared.<br>
> > #(1 2 3) collectX: [:x :i | x + i].<br>
> <br>
> That's hacky.<br>
> <br>
> I would then rather use withIndexCollect. It does what it says on the tin.<br>
> <br>
> > But the following does not work:<br>
> > #(1 2 3) collectX: #+.<br>
> ><br>
> > Maybe I would rather need something like #value:cull: for an optional second argument?<br>
> ><br>
> <br>
> you can use cull:cull: anyways.<br>
> <br>
> > In general, from the point of scripting convenience, I would love Symbol to support many more protocols of BlockClosure. What about:<br>
> > Symbol >> #asBlock<br>
> > ^ self numArgs caseOf: {<br>
> > [0] -> [[:rcvr | rcvr perform: self]].<br>
> > [1] -> [[:rcvr :arg | rcvr perform: self with: arg]].<br>
> > [2] -> [[:rcrv :arg1 :arg2 | rcrv perform: self with: arg1 with: arg2]].<br>
> > ... }<br>
> ><br>
> that's not too bad :D<br>
> but there is already perform:withArguments:, so this should be simpler?<br>
> <br>
> Best regards<br>
>         -Tobias<br>
> <br>
> <br>
><br>
</blockquote></div></div>