[Petal] Does Petal support a simple while loop?

Fergal Daly fergal at esatclear.ie
Sun Jun 22 15:02:56 BST 2003


The current way to do it is to dump all those elements into an array then 
petal:repeat over it. Of course then you lose the advantages of using an 
iterator - like being able to pass around massive collections of data without 
copying and generating the next element on the fly etc. I'm all on for 
allowing Petal to use iterators and I think Perl 6 will be full of them but 
I'm not all on for general while loops in Petal. Perhaps specific support for 
iterators would be better.

Allowing while loops with arbitrary conditions would be easy enough but it 
pushes Petal further towards being a very bad programming langauge rather 
than a very good templating language.

In most languages, an iterator needs 2 methods, hasNext() to check if there is 
a next item and getNext() to get it when you want it. Perl can do it with 
just one method.

The next() method you described will not work for collections that contain 
undef elements, so although it's OK for the collections you're dealing with, 
it can't handle the general case.

To handle the general case in 1 method, you return either a 1 item list 
($next_item) or an empty list () when there are no more items. Then do

while (my ($next) = $list->next)
{
}

This will work whether next() returns (undef) or (0) because the while will 
see a non-empty list which evaluates to true.

Iterators are an excellent programming pattern so support for 1- and 2-method 
iterators in Petal would be a good thing. How about extending the repeat 
syntax to up to 4 arguments (even writing that sentence makes me cringe but 
I'll keep going)

petal:repeat="item array_path getNext hasNext">

with end_method being optional. Why 4 arguments? If you want to loop over a 
collection, you need somewhere to store the current item and you need to know 
how to find your collection - so far that's just the same as the old repeat 
syntax - if your collection is actually an iterator then you also need the 
name of the method for producing the next item and (possibly) the name of the 
method for telling you when to stop.

4 arguments would results in this code

my $array = $hash->{"array_path"};
while ($array->hasNext)
{
	$hash->{"item"} = $array->getNext;
	# ...
}

3 arguments would be the Perlish 1-method iterator and would produce this code

my $array = $hash->{"array_path"};
while (($hash->{"item"}) = $array->getNext)
{
	# ...
}

Maybe overloading the repeat syntax is a bad idea, maybe there should be a 
petal:iterator tag.

Another problem is that even though they look very similar, there's a big 
difference between

petal:iterator="item it getNext"

and

petal:iterator="item it getNext hasNext"

hasNext is not simply an optional argument, it changes the meaning of the 
first argument in a confusing way, so that it must return ($item) instead of 
$item. Maybe they should each have their own tag...

I think the patches are easy, just deciding what to implelement is the hard 
part,

F

On Sunday 22 June 2003 00:13, Grant McLean wrote:
> I know that petal:repeat can be used to iterate through an arrayref
> of hashrefs like this:
> 
>    <ul>
>      <li petal:repeat="row hashlist">
>        <span petal:replace="row/product_id">Product ID</span>:
>        <span petal:replace="row/description">Description</span>
>      </li>
>    </ul>
> 
> What I'd like to do is use a resultset object with a ->next() method
> like this:
> 
>    <ul>
>      <li petal:repeat="row rs/next">
>        <span petal:replace="row/product_id">Product ID</span>:
>        <span petal:replace="row/description">Description</span>
>      </li>
>    </ul>
> 
> ie: the expression (method call) is evaluated repeatedly until it
> returns undef.
> 
> Is there some way to do this already?  If not, should I whip up a
> patch?
> 
> Regard
> Grant



More information about the Petal mailing list