Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[RfC] Yet another iterator proposal.

10 views
Skip to first unread message

Leopold Toetsch

unread,
Mar 10, 2003, 10:17:35 AM3/10/03
to P6I

1) Aggregates and Strings implement the nextkey_keyed vtable
method/function respectively.

This gets one additional parameter:
INTVAL what (e.g. 0=first, 1=next, 2=prev, 3=last)
to reset the iterator and allow scan in both directions.

(Note Pxxx below should indicate the usage of the P-reg)

2) The iterator is a new PMC class which implements these vtables:

new PIter, .PIter, PAggregate
// create a new iterator and attach the aggregate to it

set PIter, 0 // reset iterator, prepare from first

shift PVal, PIter // get first value from front

This doesn't actually change the aggregate, but should simulate
to to so, i.e. PVal is the first value, *and* PIter has the semantics
of the aggregate, as if the first value has been shifted off.
This should reflect a (car, cdr) which could be handy for
functional programming stuff.

shift PVal, PIter // get second value

set PIter, 3 // reset, prepare from last

pop PVal, PIter // pop last val

Now, the iterator itself should have the same sematics as the
aggregate it points to:

assign PIter, PIntArray // attach a different array to iter?
set PIter, 0 // reset
shift I0, Piter // get PIntArrray[0]
set I1, PIter[0] // == PIntArrary[1]
set I2, PIter[1] // == PIntArrary[2]

This is probably not very meaningful for hashes, but arrays can do
it simply.

So, the iterator also has all get_<x>_keyed_* methods implemented,
which are passed on to the aggregate, but no set_<x>_keyed methods,
iterators are readonly. This could also catch common errors, where
the aggregate is changed during iteration. OTOH perl always gave you
enough rope, to shoot yourself in the foot :)

3) The iterator PMC

It would need 2 pointers: a KEY * having the state of the current
index and the data * pointer to the aggregate. This ought to be enough
to implement this functionality.

4) Iterating over strings

Should work the same. The iterator holds the COWed substring and the
offset in the KEY, the COWed substring should be reused on iterations.

Comments welcome
leo

Steve Fink

unread,
Apr 27, 2003, 4:39:19 AM4/27/03
to Leopold Toetsch, P6I
On Mar-10, Leopold Toetsch wrote:
>
> 1) Aggregates and Strings implement the nextkey_keyed vtable
> method/function respectively.
>
> This gets one additional parameter:
> INTVAL what (e.g. 0=first, 1=next, 2=prev, 3=last)
> to reset the iterator and allow scan in both directions.

Okay.

> 2) The iterator is a new PMC class which implements these vtables:
>
> new PIter, .PIter, PAggregate
> // create a new iterator and attach the aggregate to it
>
> set PIter, 0 // reset iterator, prepare from first

How would you iterate over hash values (as opposed to keys)? How about
hash entries (ie, <key,value> pairs as in perl5's each %foo)? And what
about multidimensional aggregates?

> shift PVal, PIter // get first value from front
>
> This doesn't actually change the aggregate, but should simulate
> to to so, i.e. PVal is the first value, *and* PIter has the semantics
> of the aggregate, as if the first value has been shifted off.
> This should reflect a (car, cdr) which could be handy for
> functional programming stuff.

Seems a little odd, but I guess it makes sense.

> shift PVal, PIter // get second value
>
> set PIter, 3 // reset, prepare from last
>
> pop PVal, PIter // pop last val

I understand what this means if you use it exactly as you
demonstrated: seeking to the end, and then only using pop to access
elements. But what does it mean if you do

set PIter, 0
shift P0, PIter
pop P0, PIter
shift P0, PIter

Is that 'pop' invalid? Does an array iterator contain a single index
as its state, or a <begin,end> range?

> Now, the iterator itself should have the same sematics as the
> aggregate it points to:
>
> assign PIter, PIntArray // attach a different array to iter?
> set PIter, 0 // reset
> shift I0, Piter // get PIntArrray[0]
> set I1, PIter[0] // == PIntArrary[1]
> set I2, PIter[1] // == PIntArrary[2]

What if your iterator is working backwards? What element would I0 have
if you did

set PIter, 3
set I0, PIter[0]

What if you did a pop before you accessed element 0? Could you use
negative indexes?

> So, the iterator also has all get_<x>_keyed_* methods implemented,
> which are passed on to the aggregate, but no set_<x>_keyed methods,
> iterators are readonly. This could also catch common errors, where
> the aggregate is changed during iteration.

Huh? How would this catch modifications while you were iterating? Or
do you mean that generally (iterators could detect modifications, but
the fact that you have get_* but not set_* has nothing to do with that
detection)?

> 4) Iterating over strings
>
> Should work the same. The iterator holds the COWed substring and the
> offset in the KEY, the COWed substring should be reused on iterations.

Would we guarantee that, in the cases of strings only, it is legal to
modify a string with iterators on it, but that the iterators will
always see a snapshot of the string at the time they began iteration?
It seems like it might be convenient at times.

> Comments welcome
> leo

Comments given, just a tiny bit delayed. :-)

Leopold Toetsch

unread,
Apr 28, 2003, 2:36:00 AM4/28/03
to Steve Fink, P6I
Steve Fink wrote:

> On Mar-10, Leopold Toetsch wrote:

> How would you iterate over hash values (as opposed to keys)? How about
> hash entries (ie, <key,value> pairs as in perl5's each %foo)?


Iterate over keys and obtain the corresponding value - probably.

> ... And what
> about multidimensional aggregates?


One iterator per dimension? Dunno yet.


> I understand what this means if you use it exactly as you
> demonstrated: seeking to the end, and then only using pop to access
> elements. But what does it mean if you do
>
> set PIter, 0
> shift P0, PIter
> pop P0, PIter
> shift P0, PIter
>
> Is that 'pop' invalid? Does an array iterator contain a single index
> as its state, or a <begin,end> range?


I think iteration is oneway only, so it would be illegal as only one
begin or end state is stored in the iterator.


> What if your iterator is working backwards? What element would I0 have
> if you did
>
> set PIter, 3
> set I0, PIter[0]


The first element.


> What if you did a pop before you accessed element 0? Could you use
> negative indexes?


PIter[-1] would be the "current" last element always.


>
>
>> So, the iterator also has all get_<x>_keyed_* methods implemented,
>> which are passed on to the aggregate, but no set_<x>_keyed methods,
>> iterators are readonly. This could also catch common errors, where
>> the aggregate is changed during iteration.
>>
>
> Huh? How would this catch modifications while you were iterating? Or
> do you mean that generally (iterators could detect modifications, but
> the fact that you have get_* but not set_* has nothing to do with that
> detection)?


As the iterator should behave like the aggregate it works on, the HL
could emit code that uses the iterator instead of the aggregate. And due
to the missing set_* methods any modifications would be catched.


> Would we guarantee that, in the cases of strings only, it is legal to
> modify a string with iterators on it, but that the iterators will
> always see a snapshot of the string at the time they began iteration?
> It seems like it might be convenient at times.


This is a design question. Either use the original string or a COWed copy.


> Comments given, just a tiny bit delayed. :-)

Better then nether, thanks. And in the meantime :-) I had sent a proof
of concept patch.

leo

0 new messages