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
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. :-)
> 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