looking for another iterator :)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

looking for another iterator :)

Stephane Ducasse-3
Hi

I would like to iterate at max on a certain amount of elements in a collection.
And I was wondering if we have such iterator.

Stef

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Ben Coman
On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]> wrote:
> Hi
>
> I would like to iterate at max on a certain amount of elements in a collection.
> And I was wondering if we have such iterator.

I'm not clear what functionality your asking for.  Could you present
it as code & result if you assumed the iterator you want was
available?

cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Clément Béra
I don't think we do. Do you need it on SequenceableCollection or HashedCollection too ?

Recently I was trying to iterate over the first N elements of a collection and since there was no #first:do: I used #from:to:do:. I guess you could use that too:

aCollection from: 1 to: (aCollection size min: 1000) do: aBlock

Which guarantees you iterate at max over 1000 elements. But that API is SequenceableCollection specific.

On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]> wrote:
> Hi
>
> I would like to iterate at max on a certain amount of elements in a collection.
> And I was wondering if we have such iterator.

I'm not clear what functionality your asking for.  Could you present
it as code & result if you assumed the iterator you want was
available?

cheers -ben




--
Clément Béra
Pharo consortium engineer
Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Stephane Ducasse-3
Hi Ben and Clement

I have a collection (a dictionary in my case) and I want to get
maximum 5 bindings out of it and iterate on them.
I want keysAndValuesDo: or do: but only up to 5 elements.

aDict atMax: 5 do: [:each | ]

So I learned from:to:do:

aCollection atMax: 5 do: [:each | ]

Does it make sense?

Stef

On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:

> I don't think we do. Do you need it on SequenceableCollection or
> HashedCollection too ?
>
> Recently I was trying to iterate over the first N elements of a collection
> and since there was no #first:do: I used #from:to:do:. I guess you could use
> that too:
>
> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>
> Which guarantees you iterate at max over 1000 elements. But that API is
> SequenceableCollection specific.
>
> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>
>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>> wrote:
>> > Hi
>> >
>> > I would like to iterate at max on a certain amount of elements in a
>> > collection.
>> > And I was wondering if we have such iterator.
>>
>> I'm not clear what functionality your asking for.  Could you present
>> it as code & result if you assumed the iterator you want was
>> available?
>>
>> cheers -ben
>>
>
>
>
> --
> Clément Béra
> Pharo consortium engineer
> https://clementbera.wordpress.com/
> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Stephane Ducasse-3
I thought about something like that...

SequenceableCollection >> atMax: numberOfItems do: aBlock
    "Execute the iteration with at the maximum numberOfItems. If the
receiver contains less than numberOfItems iterate them all."
    1 to: (numberOfItems min: self size) do: [:index | aBlock value:
(self at: index)]

This is an abstraction that we need to treat some samples.

Stef

On Sun, Jan 21, 2018 at 5:47 PM, Stephane Ducasse
<[hidden email]> wrote:

> Hi Ben and Clement
>
> I have a collection (a dictionary in my case) and I want to get
> maximum 5 bindings out of it and iterate on them.
> I want keysAndValuesDo: or do: but only up to 5 elements.
>
> aDict atMax: 5 do: [:each | ]
>
> So I learned from:to:do:
>
> aCollection atMax: 5 do: [:each | ]
>
> Does it make sense?
>
> Stef
>
> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>> I don't think we do. Do you need it on SequenceableCollection or
>> HashedCollection too ?
>>
>> Recently I was trying to iterate over the first N elements of a collection
>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>> that too:
>>
>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>
>> Which guarantees you iterate at max over 1000 elements. But that API is
>> SequenceableCollection specific.
>>
>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>
>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>> wrote:
>>> > Hi
>>> >
>>> > I would like to iterate at max on a certain amount of elements in a
>>> > collection.
>>> > And I was wondering if we have such iterator.
>>>
>>> I'm not clear what functionality your asking for.  Could you present
>>> it as code & result if you assumed the iterator you want was
>>> available?
>>>
>>> cheers -ben
>>>
>>
>>
>>
>> --
>> Clément Béra
>> Pharo consortium engineer
>> https://clementbera.wordpress.com/
>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Stephane Ducasse-3
Now an iterator getting atMax: x elements could be better because we
could them combined it with collect:, detect:...

Stef

On Sun, Jan 21, 2018 at 5:56 PM, Stephane Ducasse
<[hidden email]> wrote:

> I thought about something like that...
>
> SequenceableCollection >> atMax: numberOfItems do: aBlock
>     "Execute the iteration with at the maximum numberOfItems. If the
> receiver contains less than numberOfItems iterate them all."
>     1 to: (numberOfItems min: self size) do: [:index | aBlock value:
> (self at: index)]
>
> This is an abstraction that we need to treat some samples.
>
> Stef
>
> On Sun, Jan 21, 2018 at 5:47 PM, Stephane Ducasse
> <[hidden email]> wrote:
>> Hi Ben and Clement
>>
>> I have a collection (a dictionary in my case) and I want to get
>> maximum 5 bindings out of it and iterate on them.
>> I want keysAndValuesDo: or do: but only up to 5 elements.
>>
>> aDict atMax: 5 do: [:each | ]
>>
>> So I learned from:to:do:
>>
>> aCollection atMax: 5 do: [:each | ]
>>
>> Does it make sense?
>>
>> Stef
>>
>> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>>> I don't think we do. Do you need it on SequenceableCollection or
>>> HashedCollection too ?
>>>
>>> Recently I was trying to iterate over the first N elements of a collection
>>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>>> that too:
>>>
>>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>>
>>> Which guarantees you iterate at max over 1000 elements. But that API is
>>> SequenceableCollection specific.
>>>
>>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>>
>>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>>> wrote:
>>>> > Hi
>>>> >
>>>> > I would like to iterate at max on a certain amount of elements in a
>>>> > collection.
>>>> > And I was wondering if we have such iterator.
>>>>
>>>> I'm not clear what functionality your asking for.  Could you present
>>>> it as code & result if you assumed the iterator you want was
>>>> available?
>>>>
>>>> cheers -ben
>>>>
>>>
>>>
>>>
>>> --
>>> Clément Béra
>>> Pharo consortium engineer
>>> https://clementbera.wordpress.com/
>>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Ben Coman
In reply to this post by Stephane Ducasse-3
On 22 January 2018 at 00:47, Stephane Ducasse <[hidden email]> wrote:

> Hi Ben and Clement
>
> I have a collection (a dictionary in my case) and I want to get
> maximum 5 bindings out of it and iterate on them.
> I want keysAndValuesDo: or do: but only up to 5 elements.
>
> aDict atMax: 5 do: [:each | ]
>
> So I learned from:to:do:
>
> aCollection atMax: 5 do: [:each | ]
>
> Does it make sense?

Just some random thoughts.  Perhaps something more generic...

aDict doN: [ :each :n | aCollection add: each]
          while: [ :each :n | n <=5 ]

For #select: & #collect:  there is a distinction to make whether it is
5 elements processed
or 5 elements returned.

aDict select: [ :each | "do something" ]
          while:
            [ :iterator | iterator selectedCount <= 5 ].    "or..."
            [ :iterator | iterator processedCount <= 5 ].     "or..."
            [ :iterator | (iterator element ~= "breakElement")

cheers -ben

> Stef
>
> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>> I don't think we do. Do you need it on SequenceableCollection or
>> HashedCollection too ?
>>
>> Recently I was trying to iterate over the first N elements of a collection
>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>> that too:
>>
>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>
>> Which guarantees you iterate at max over 1000 elements. But that API is
>> SequenceableCollection specific.
>>
>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>
>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>> wrote:
>>> > Hi
>>> >
>>> > I would like to iterate at max on a certain amount of elements in a
>>> > collection.
>>> > And I was wondering if we have such iterator.
>>>
>>> I'm not clear what functionality your asking for.  Could you present
>>> it as code & result if you assumed the iterator you want was
>>> available?
>>>
>>> cheers -ben
>>>
>>
>>
>>
>> --
>> Clément Béra
>> Pharo consortium engineer
>> https://clementbera.wordpress.com/
>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

jgfoster
In reply to this post by Stephane Ducasse-3
Since ‘atMax:’ doesn’t seem as clear to me, I’d prefer ‘upToMax:’ or ‘withMax:’ or (especially) the following:

upTo: anInteger timesDo: aBlock
upTo: anInteger timesSelect: aBlock
upTo: anInteger timesCollect: aBlock

James Foster

> On Jan 21, 2018, at 8:56 AM, Stephane Ducasse <[hidden email]> wrote:
>
> I thought about something like that...
>
> SequenceableCollection >> atMax: numberOfItems do: aBlock
>    "Execute the iteration with at the maximum numberOfItems. If the
> receiver contains less than numberOfItems iterate them all."
>    1 to: (numberOfItems min: self size) do: [:index | aBlock value:
> (self at: index)]
>
> This is an abstraction that we need to treat some samples.
>
> Stef
>
> On Sun, Jan 21, 2018 at 5:47 PM, Stephane Ducasse
> <[hidden email]> wrote:
>> Hi Ben and Clement
>>
>> I have a collection (a dictionary in my case) and I want to get
>> maximum 5 bindings out of it and iterate on them.
>> I want keysAndValuesDo: or do: but only up to 5 elements.
>>
>> aDict atMax: 5 do: [:each | ]
>>
>> So I learned from:to:do:
>>
>> aCollection atMax: 5 do: [:each | ]
>>
>> Does it make sense?
>>
>> Stef
>>
>> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>>> I don't think we do. Do you need it on SequenceableCollection or
>>> HashedCollection too ?
>>>
>>> Recently I was trying to iterate over the first N elements of a collection
>>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>>> that too:
>>>
>>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>>
>>> Which guarantees you iterate at max over 1000 elements. But that API is
>>> SequenceableCollection specific.
>>>
>>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>>
>>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>>> wrote:
>>>>> Hi
>>>>>
>>>>> I would like to iterate at max on a certain amount of elements in a
>>>>> collection.
>>>>> And I was wondering if we have such iterator.
>>>>
>>>> I'm not clear what functionality your asking for.  Could you present
>>>> it as code & result if you assumed the iterator you want was
>>>> available?
>>>>
>>>> cheers -ben
>>>>
>>>
>>>
>>>
>>> --
>>> Clément Béra
>>> Pharo consortium engineer
>>> https://clementbera.wordpress.com/
>>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>
>


Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Richard Sargent
Administrator
SomeCollection every: 5 do: [:subset | subset collect: [:each | ...]]
etc.

If you want the first five only, return from the do: block.

Possibly, #every: by itself answers an iterator / collection conforming instance.

On Jan 21, 2018 14:47, "James Foster" <[hidden email]> wrote:
Since ‘atMax:’ doesn’t seem as clear to me, I’d prefer ‘upToMax:’ or ‘withMax:’ or (especially) the following:

upTo: anInteger timesDo: aBlock
upTo: anInteger timesSelect: aBlock
upTo: anInteger timesCollect: aBlock

James Foster

> On Jan 21, 2018, at 8:56 AM, Stephane Ducasse <[hidden email]> wrote:
>
> I thought about something like that...
>
> SequenceableCollection >> atMax: numberOfItems do: aBlock
>    "Execute the iteration with at the maximum numberOfItems. If the
> receiver contains less than numberOfItems iterate them all."
>    1 to: (numberOfItems min: self size) do: [:index | aBlock value:
> (self at: index)]
>
> This is an abstraction that we need to treat some samples.
>
> Stef
>
> On Sun, Jan 21, 2018 at 5:47 PM, Stephane Ducasse
> <[hidden email]> wrote:
>> Hi Ben and Clement
>>
>> I have a collection (a dictionary in my case) and I want to get
>> maximum 5 bindings out of it and iterate on them.
>> I want keysAndValuesDo: or do: but only up to 5 elements.
>>
>> aDict atMax: 5 do: [:each | ]
>>
>> So I learned from:to:do:
>>
>> aCollection atMax: 5 do: [:each | ]
>>
>> Does it make sense?
>>
>> Stef
>>
>> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>>> I don't think we do. Do you need it on SequenceableCollection or
>>> HashedCollection too ?
>>>
>>> Recently I was trying to iterate over the first N elements of a collection
>>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>>> that too:
>>>
>>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>>
>>> Which guarantees you iterate at max over 1000 elements. But that API is
>>> SequenceableCollection specific.
>>>
>>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>>
>>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>>> wrote:
>>>>> Hi
>>>>>
>>>>> I would like to iterate at max on a certain amount of elements in a
>>>>> collection.
>>>>> And I was wondering if we have such iterator.
>>>>
>>>> I'm not clear what functionality your asking for.  Could you present
>>>> it as code & result if you assumed the iterator you want was
>>>> available?
>>>>
>>>> cheers -ben
>>>>
>>>
>>>
>>>
>>> --
>>> Clément Béra
>>> Pharo consortium engineer
>>> https://clementbera.wordpress.com/
>>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>
>


Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Ben Coman
In reply to this post by Stephane Ducasse-3
On 22 January 2018 at 00:47, Stephane Ducasse <[hidden email]> wrote:
> Hi Ben and Clement
>
> I have a collection (a dictionary in my case) and I want to get
> maximum 5 bindings out of it and iterate on them.
> I want keysAndValuesDo: or do: but only up to 5 elements.
>
> aDict atMax: 5 do: [:each | ]

"atMax" sound a bit like comparison rather than counting. Perhaps
better would be...
    aDict atMost: 5 do: [:each | ]   "or"
    aDict for: 5 do: [:each | ]

but rather than introduce three or more messages...
    aDict atMost: 5 do: [:each| ... ]
    aDict atMost: 5 select: [:each| ... ]
    aDict atMost: 5 collect: [:each| ... ]

why not introduce just one method?....
    (aDict any: 5) do: [:each| ... ]
    (aDict any: 5) select: [:each| ... ]
    (aDict any: 5) collect: [:each| ... ]


cheers -ben


> So I learned from:to:do:
>
> aCollection atMax: 5 do: [:each | ]
>
> Does it make sense?
>
> Stef
>
> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>> I don't think we do. Do you need it on SequenceableCollection or
>> HashedCollection too ?
>>
>> Recently I was trying to iterate over the first N elements of a collection
>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>> that too:
>>
>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>
>> Which guarantees you iterate at max over 1000 elements. But that API is
>> SequenceableCollection specific.
>>
>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>
>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>> wrote:
>>> > Hi
>>> >
>>> > I would like to iterate at max on a certain amount of elements in a
>>> > collection.
>>> > And I was wondering if we have such iterator.
>>>
>>> I'm not clear what functionality your asking for.  Could you present
>>> it as code & result if you assumed the iterator you want was
>>> available?
>>>
>>> cheers -ben
>>>
>>
>>
>>
>> --
>> Clément Béra
>> Pharo consortium engineer
>> https://clementbera.wordpress.com/
>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Guillermo Polito
In most collection libraries I know there is the "take" function coming from the functional world that does that:

#(1 2 3 4 5 6 7 8) take: 5
  => #(1 2 3 4 5)

#(1 2 3 4) take: 5
  => #(1 2 3 4)

Now, I understand there are two different things in here.
 - First is the fact that we would like to apply this iterator to more than sequenceable collections. I think that the name "take" is order agnostic in that sense.
 - The other thing is that people would like to not calculate the sub-collection... The problem is that we will end up with ugly combinations of selectors like

take:thenDo:
take:thenCollect:
take:thenSelect:
...

And that pattern already exists also for:

select:thenCollect:
select:thenDo:

collect:as:
select:as:

...

I think I would like to have a more composable kind of iterators/collections. There are Transducers that make "iterators" kind of command objects that you can apply on a collection. Personally I don't like the API choice but the idea behind is nice:


sum := #+ init: 0.
sum1 := #(1 1 1) reduce: sum.
sum2 := (1 to: 1000) transduce: #odd filter reduce: sum.

And there are XTreams that allows one to work on a collection as a stream and then compose decorators on top. This means however that we need to create a stream and "close" it to obtain the resulting collection on every manipulation.


((aCollection reading collect: [ ... ]) select: [ ... ]) rest.

Guille

On Mon, Jan 22, 2018 at 4:11 AM, Ben Coman <[hidden email]> wrote:
On 22 January 2018 at 00:47, Stephane Ducasse <[hidden email]> wrote:
> Hi Ben and Clement
>
> I have a collection (a dictionary in my case) and I want to get
> maximum 5 bindings out of it and iterate on them.
> I want keysAndValuesDo: or do: but only up to 5 elements.
>
> aDict atMax: 5 do: [:each | ]

"atMax" sound a bit like comparison rather than counting. Perhaps
better would be...
    aDict atMost: 5 do: [:each | ]   "or"
    aDict for: 5 do: [:each | ]

but rather than introduce three or more messages...
    aDict atMost: 5 do: [:each| ... ]
    aDict atMost: 5 select: [:each| ... ]
    aDict atMost: 5 collect: [:each| ... ]

why not introduce just one method?....
    (aDict any: 5) do: [:each| ... ]
    (aDict any: 5) select: [:each| ... ]
    (aDict any: 5) collect: [:each| ... ]


cheers -ben


> So I learned from:to:do:
>
> aCollection atMax: 5 do: [:each | ]
>
> Does it make sense?
>
> Stef
>
> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>> I don't think we do. Do you need it on SequenceableCollection or
>> HashedCollection too ?
>>
>> Recently I was trying to iterate over the first N elements of a collection
>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>> that too:
>>
>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>
>> Which guarantees you iterate at max over 1000 elements. But that API is
>> SequenceableCollection specific.
>>
>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>
>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>> wrote:
>>> > Hi
>>> >
>>> > I would like to iterate at max on a certain amount of elements in a
>>> > collection.
>>> > And I was wondering if we have such iterator.
>>>
>>> I'm not clear what functionality your asking for.  Could you present
>>> it as code & result if you assumed the iterator you want was
>>> available?
>>>
>>> cheers -ben
>>>
>>
>>
>>
>> --
>> Clément Béra
>> Pharo consortium engineer
>> https://clementbera.wordpress.com/
>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>




--

   

Guille Polito

Research Engineer

Centre de Recherche en Informatique, Signal et Automatique de Lille

CRIStAL - UMR 9189

French National Center for Scientific Research - http://www.cnrs.fr


Web: http://guillep.github.io

Phone: +33 06 52 70 66 13

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Sven Van Caekenberghe-2
yes, we need composition to avoid API explosion (things are already very bad in this respect)

> On 22 Jan 2018, at 10:38, Guillermo Polito <[hidden email]> wrote:
>
> In most collection libraries I know there is the "take" function coming from the functional world that does that:
>
> #(1 2 3 4 5 6 7 8) take: 5
>   => #(1 2 3 4 5)
>
> #(1 2 3 4) take: 5
>   => #(1 2 3 4)
>
> Now, I understand there are two different things in here.
>  - First is the fact that we would like to apply this iterator to more than sequenceable collections. I think that the name "take" is order agnostic in that sense.
>  - The other thing is that people would like to not calculate the sub-collection... The problem is that we will end up with ugly combinations of selectors like
>
> take:thenDo:
> take:thenCollect:
> take:thenSelect:
> ...
>
> And that pattern already exists also for:
>
> select:thenCollect:
> select:thenDo:
>
> collect:as:
> select:as:
>
> ...
>
> I think I would like to have a more composable kind of iterators/collections. There are Transducers that make "iterators" kind of command objects that you can apply on a collection. Personally I don't like the API choice but the idea behind is nice:
>
> https://github.com/Pharophile/Transducers
>
> sum := #+ init: 0.
> sum1 := #(1 1 1) reduce: sum.
> sum2 := (1 to: 1000) transduce: #odd filter reduce: sum.
>
>
> And there are XTreams that allows one to work on a collection as a stream and then compose decorators on top. This means however that we need to create a stream and "close" it to obtain the resulting collection on every manipulation.
>
> https://github.com/mkobetic/Xtreams
> https://code.google.com/archive/p/xtreams/wikis/Core.wiki
>
> ((aCollection reading collect: [ ... ]) select: [ ... ]) rest.
>
> Guille
>
> On Mon, Jan 22, 2018 at 4:11 AM, Ben Coman <[hidden email]> wrote:
> On 22 January 2018 at 00:47, Stephane Ducasse <[hidden email]> wrote:
> > Hi Ben and Clement
> >
> > I have a collection (a dictionary in my case) and I want to get
> > maximum 5 bindings out of it and iterate on them.
> > I want keysAndValuesDo: or do: but only up to 5 elements.
> >
> > aDict atMax: 5 do: [:each | ]
>
> "atMax" sound a bit like comparison rather than counting. Perhaps
> better would be...
>     aDict atMost: 5 do: [:each | ]   "or"
>     aDict for: 5 do: [:each | ]
>
> but rather than introduce three or more messages...
>     aDict atMost: 5 do: [:each| ... ]
>     aDict atMost: 5 select: [:each| ... ]
>     aDict atMost: 5 collect: [:each| ... ]
>
> why not introduce just one method?....
>     (aDict any: 5) do: [:each| ... ]
>     (aDict any: 5) select: [:each| ... ]
>     (aDict any: 5) collect: [:each| ... ]
>
>
> cheers -ben
>
>
> > So I learned from:to:do:
> >
> > aCollection atMax: 5 do: [:each | ]
> >
> > Does it make sense?
> >
> > Stef
> >
> > On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
> >> I don't think we do. Do you need it on SequenceableCollection or
> >> HashedCollection too ?
> >>
> >> Recently I was trying to iterate over the first N elements of a collection
> >> and since there was no #first:do: I used #from:to:do:. I guess you could use
> >> that too:
> >>
> >> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
> >>
> >> Which guarantees you iterate at max over 1000 elements. But that API is
> >> SequenceableCollection specific.
> >>
> >> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
> >>>
> >>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
> >>> wrote:
> >>> > Hi
> >>> >
> >>> > I would like to iterate at max on a certain amount of elements in a
> >>> > collection.
> >>> > And I was wondering if we have such iterator.
> >>>
> >>> I'm not clear what functionality your asking for.  Could you present
> >>> it as code & result if you assumed the iterator you want was
> >>> available?
> >>>
> >>> cheers -ben
> >>>
> >>
> >>
> >>
> >> --
> >> Clément Béra
> >> Pharo consortium engineer
> >> https://clementbera.wordpress.com/
> >> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
> >
>
>
>
>
> --
>    
> Guille Polito
> Research Engineer
>
> Centre de Recherche en Informatique, Signal et Automatique de Lille
> CRIStAL - UMR 9189
> French National Center for Scientific Research - http://www.cnrs.fr
>
> Web: http://guillep.github.io
> Phone: +33 06 52 70 66 13


Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Steffen Märcker
Hi!

this is straightforward with Transducers, e.g.,

> (Take n: 5) <~ #(1 2 3 4 5 6 7 8).
or
> #(1 2 3 4 5 6 7 8) transduce take: 5.

The different primitives like take, drop, map, filter, etc. are composable  
and do not generate intermediate representations.
The bad news are, that the Pharo port is incomplete and I won't have the  
time until April to finish it.

Best, Steffen

Am .01.2018, 10:57 Uhr, schrieb Sven Van Caekenberghe <[hidden email]>:

> 5



Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Esteban A. Maringolo
In reply to this post by Sven Van Caekenberghe-2
2018-01-22 6:57 GMT-03:00 Sven Van Caekenberghe <[hidden email]>:
> yes, we need composition to avoid API explosion (things are already very bad in this respect)

And the names of the proposed selectors suggests it could be even worst.

+1 to composition.

Esteban A. Maringolo

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Stephane Ducasse-3
In reply to this post by Steffen Märcker
On Mon, Jan 22, 2018 at 11:26 AM, Steffen Märcker <[hidden email]> wrote:

> Hi!
>
> this is straightforward with Transducers, e.g.,
>
>> (Take n: 5) <~ #(1 2 3 4 5 6 7 8).
>
> or
>>
>> #(1 2 3 4 5 6 7 8) transduce take: 5.
>
>
> The different primitives like take, drop, map, filter, etc. are composable
> and do not generate intermediate representations.
> The bad news are, that the Pharo port is incomplete and I won't have the
> time until April to finish it.

oh there is not stress.
What I would like to see is
- what is the API in terms of vocabulary (ie drop the same as reject)
- can we reexpress some of our iterators? what is the cost?

Stef

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Stephane Ducasse-3
In reply to this post by Sven Van Caekenberghe-2
I like the pharophile :)


On Mon, Jan 22, 2018 at 10:57 AM, Sven Van Caekenberghe <[hidden email]> wrote:

> yes, we need composition to avoid API explosion (things are already very bad in this respect)
>
>> On 22 Jan 2018, at 10:38, Guillermo Polito <[hidden email]> wrote:
>>
>> In most collection libraries I know there is the "take" function coming from the functional world that does that:
>>
>> #(1 2 3 4 5 6 7 8) take: 5
>>   => #(1 2 3 4 5)
>>
>> #(1 2 3 4) take: 5
>>   => #(1 2 3 4)
>>
>> Now, I understand there are two different things in here.
>>  - First is the fact that we would like to apply this iterator to more than sequenceable collections. I think that the name "take" is order agnostic in that sense.
>>  - The other thing is that people would like to not calculate the sub-collection... The problem is that we will end up with ugly combinations of selectors like
>>
>> take:thenDo:
>> take:thenCollect:
>> take:thenSelect:
>> ...
>>
>> And that pattern already exists also for:
>>
>> select:thenCollect:
>> select:thenDo:
>>
>> collect:as:
>> select:as:
>>
>> ...
>>
>> I think I would like to have a more composable kind of iterators/collections. There are Transducers that make "iterators" kind of command objects that you can apply on a collection. Personally I don't like the API choice but the idea behind is nice:
>>
>> https://github.com/Pharophile/Transducers
>>
>> sum := #+ init: 0.
>> sum1 := #(1 1 1) reduce: sum.
>> sum2 := (1 to: 1000) transduce: #odd filter reduce: sum.
>>
>>
>> And there are XTreams that allows one to work on a collection as a stream and then compose decorators on top. This means however that we need to create a stream and "close" it to obtain the resulting collection on every manipulation.
>>
>> https://github.com/mkobetic/Xtreams
>> https://code.google.com/archive/p/xtreams/wikis/Core.wiki
>>
>> ((aCollection reading collect: [ ... ]) select: [ ... ]) rest.
>>
>> Guille
>>
>> On Mon, Jan 22, 2018 at 4:11 AM, Ben Coman <[hidden email]> wrote:
>> On 22 January 2018 at 00:47, Stephane Ducasse <[hidden email]> wrote:
>> > Hi Ben and Clement
>> >
>> > I have a collection (a dictionary in my case) and I want to get
>> > maximum 5 bindings out of it and iterate on them.
>> > I want keysAndValuesDo: or do: but only up to 5 elements.
>> >
>> > aDict atMax: 5 do: [:each | ]
>>
>> "atMax" sound a bit like comparison rather than counting. Perhaps
>> better would be...
>>     aDict atMost: 5 do: [:each | ]   "or"
>>     aDict for: 5 do: [:each | ]
>>
>> but rather than introduce three or more messages...
>>     aDict atMost: 5 do: [:each| ... ]
>>     aDict atMost: 5 select: [:each| ... ]
>>     aDict atMost: 5 collect: [:each| ... ]
>>
>> why not introduce just one method?....
>>     (aDict any: 5) do: [:each| ... ]
>>     (aDict any: 5) select: [:each| ... ]
>>     (aDict any: 5) collect: [:each| ... ]
>>
>>
>> cheers -ben
>>
>>
>> > So I learned from:to:do:
>> >
>> > aCollection atMax: 5 do: [:each | ]
>> >
>> > Does it make sense?
>> >
>> > Stef
>> >
>> > On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>> >> I don't think we do. Do you need it on SequenceableCollection or
>> >> HashedCollection too ?
>> >>
>> >> Recently I was trying to iterate over the first N elements of a collection
>> >> and since there was no #first:do: I used #from:to:do:. I guess you could use
>> >> that too:
>> >>
>> >> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>> >>
>> >> Which guarantees you iterate at max over 1000 elements. But that API is
>> >> SequenceableCollection specific.
>> >>
>> >> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>> >>>
>> >>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>> >>> wrote:
>> >>> > Hi
>> >>> >
>> >>> > I would like to iterate at max on a certain amount of elements in a
>> >>> > collection.
>> >>> > And I was wondering if we have such iterator.
>> >>>
>> >>> I'm not clear what functionality your asking for.  Could you present
>> >>> it as code & result if you assumed the iterator you want was
>> >>> available?
>> >>>
>> >>> cheers -ben
>> >>>
>> >>
>> >>
>> >>
>> >> --
>> >> Clément Béra
>> >> Pharo consortium engineer
>> >> https://clementbera.wordpress.com/
>> >> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>> >
>>
>>
>>
>>
>> --
>>
>> Guille Polito
>> Research Engineer
>>
>> Centre de Recherche en Informatique, Signal et Automatique de Lille
>> CRIStAL - UMR 9189
>> French National Center for Scientific Research - http://www.cnrs.fr
>>
>> Web: http://guillep.github.io
>> Phone: +33 06 52 70 66 13
>
>

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Richard O'Keefe
In reply to this post by Stephane Ducasse-3
My own Smalltalk has these:

Enumerable
  methods for: 'enumerating'
    limit: n do: aBlock
      "Pass elements of the receiver to aBlock one at a time,
       as for #do:, but stop after n elements.  n must be a
       non-negative SmallInteger.  Which elements you get is
       for the receiver to decide."
      |count|
      n < 1 ifTrue: [
        n = 0 ifTrue: [^self]ifFalse: [self pvtCountError: n]].
      count := 0.
      self do: [:each |
        aBlock value: each.
        (count := count + 1) < n ifFalse: [^self]].
AbstractKeyedCollection
  methods for: 'enumerating'
    limit: n keysAndValuesDo: aBlock  
      "Pass keys and corresponding values of the receiver
       to aBlock one at a time, as for #keysAndValuesDo:,
       but stop after n elements.  See #limit:do:."
      |count|
      n < 1 ifTrue: [
        n = 0 ifTrue: [^self]ifFalse: [self pvtCountError: n]].
      count := 0.
      self keysAndValuesDo: [:key :value |
        aBlock value: key value: value.
        (count := count + 1) < n ifFalse: [^self]].


Enumerable is the superclass of Collection; it doesn't cover streams but does
cover 2- and 3-dimensional arrays.  AbstractKeyedCollection covers both
dictionaries and sequences. Since they only depend on #do: and #keysAndValuesDo:
respectively, they should fit nicely into some sort of Trait(s).

I gave a great deal of thought to the names, and decided on "limit" since it
is already in use in a similar sense in things like LimitedOutputStream or
#printStringLimitedTo:.  I did consider #do:limitedTo: and #keysAndValuesDo:limitedTo:
which would be more consistent with #streamContents:limitedTo:, but "heavy" things
like blocks really work better at the end.
Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Richard O'Keefe
In reply to this post by jgfoster
I thought about that for my own Smalltalk, but then realised
that I didn't know whether #upTo:timesSelect: was bounding
the number of elements *considered* or the number of elements
in the *result*, and I could argue either way.  Arguably the cleanest
way would be to have something like
 (LimitedEnumerableAdapter on: collection limit: anInteger)
    do: aBlock
    select: aBlock
    collect: aBlock
   ... *any* existing or new collection method.


On 22 January 2018 at 11:46, James Foster <[hidden email]> wrote:
Since ‘atMax:’ doesn’t seem as clear to me, I’d prefer ‘upToMax:’ or ‘withMax:’ or (especially) the following:

upTo: anInteger timesDo: aBlock
upTo: anInteger timesSelect: aBlock
upTo: anInteger timesCollect: aBlock

James Foster

> On Jan 21, 2018, at 8:56 AM, Stephane Ducasse <[hidden email]> wrote:
>
> I thought about something like that...
>
> SequenceableCollection >> atMax: numberOfItems do: aBlock
>    "Execute the iteration with at the maximum numberOfItems. If the
> receiver contains less than numberOfItems iterate them all."
>    1 to: (numberOfItems min: self size) do: [:index | aBlock value:
> (self at: index)]
>
> This is an abstraction that we need to treat some samples.
>
> Stef
>
> On Sun, Jan 21, 2018 at 5:47 PM, Stephane Ducasse
> <[hidden email]> wrote:
>> Hi Ben and Clement
>>
>> I have a collection (a dictionary in my case) and I want to get
>> maximum 5 bindings out of it and iterate on them.
>> I want keysAndValuesDo: or do: but only up to 5 elements.
>>
>> aDict atMax: 5 do: [:each | ]
>>
>> So I learned from:to:do:
>>
>> aCollection atMax: 5 do: [:each | ]
>>
>> Does it make sense?
>>
>> Stef
>>
>> On Sun, Jan 21, 2018 at 1:16 PM, Clément Bera <[hidden email]> wrote:
>>> I don't think we do. Do you need it on SequenceableCollection or
>>> HashedCollection too ?
>>>
>>> Recently I was trying to iterate over the first N elements of a collection
>>> and since there was no #first:do: I used #from:to:do:. I guess you could use
>>> that too:
>>>
>>> aCollection from: 1 to: (aCollection size min: 1000) do: aBlock
>>>
>>> Which guarantees you iterate at max over 1000 elements. But that API is
>>> SequenceableCollection specific.
>>>
>>> On Sun, Jan 21, 2018 at 11:44 AM, Ben Coman <[hidden email]> wrote:
>>>>
>>>> On 21 January 2018 at 18:36, Stephane Ducasse <[hidden email]>
>>>> wrote:
>>>>> Hi
>>>>>
>>>>> I would like to iterate at max on a certain amount of elements in a
>>>>> collection.
>>>>> And I was wondering if we have such iterator.
>>>>
>>>> I'm not clear what functionality your asking for.  Could you present
>>>> it as code & result if you assumed the iterator you want was
>>>> available?
>>>>
>>>> cheers -ben
>>>>
>>>
>>>
>>>
>>> --
>>> Clément Béra
>>> Pharo consortium engineer
>>> https://clementbera.wordpress.com/
>>> Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
>
>



Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Evan Donahue
In reply to this post by Guillermo Polito
It is also worth mentioning that there is now also the Cons library available
through the Pharo6 catalog browser. Cons is a lazy linked list that can be
used like a normal linked list, but can also be used as an iterator over
streams or infinite-sequence-generating blocks, using the usual Pharo
collections API.

myStream := (1 to: 100) readStream.
(myStream asCons take: 5) do: [ ... ].

Due to the laziness, Cons, like Clojure's transducers, doesn't build
intermediate representations, so things like #selectThenCollect: aren't
necessary.

(myList select: sBlock) collect: cBlock

 just creates an iterator and never actually creates the whole list,
although you can still treat it like a list with #first, #allButRest, etc.

The code is stable and in use in several of my projects.

Evan



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: looking for another iterator :)

Steffen Märcker
In reply to this post by Stephane Ducasse-3
Hi!

No stress is good news!

> - what is the API in terms of vocabulary (ie drop the same as reject)

These are the operations implemented so far. |= means "satisfies", i.e.,  
evaluate to true.

Drop          drop first n elements
DropWhile     drop first elements |= a block
Filter*       pick only elements |= a block
Keep*         only use elements ~= nil
Map*          map each element
MapKeys*      map each element an use as key
Partition     split after n elements
PartitionBy   split after elements |= a block
RandomSample* pick elements with probability p
Reductions    intermediate results of reduce
Remove*       = Filter not
Replace*      replace elements by LUT
Cat*          concatenate sequences
Dedupe        remove consecutive duplicates
Flatten*      flatten nested sequence
Take          pick first n elements
TakeNth       pick every n-th element
TakeWhile     pick first elements |= a block
Tee           UNIX tee, concurrent evaluation

Note, * means that the operation is parallelizable. As the operations are  
independent of the sequence class, the apply naturally to all kinds of  
sources, like collections, streams, channels and so on.

> - can we reexpress some of our iterators?

Most of them. For example, generic for all collections:

collect: aBlock
   ^self class <~ aBlock map <~ self
reject: aBlock
   ^self class <~ ablock remove <~ self
select: aBlock
   ^self class <~ aBlock filter <~ self

As said before, names are not fixed yet and there is a more classical API  
on top available, too:

collect: aBlock
   ^(self transduce map: aBlock) into: self class

> - what is the cost?

Very little. In detail:
1) Upfront there is the constant cost of instantiating the tranducers.
2) The linear cost of evaluating a nested block for each element. This is  
likely to be optimized by the JIT, as the structure is very regular.

I only did some micro-benchmarks which showed little to none impact on  
performance so far.

Best,
Steffen

12