[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