in reply to Return a list or an iterator

That is interesting. One change I'd suggest would be to not say if @foo, since that will result in the iterator returning 0 (@foo in scalar context) when the list is exhausted. Unconditionally saying shift @foo will return undef instead, which, while still ambiguous if @foo may contain undef, is more what I'd expect.

Either way, your iterator is only expecting to be called in scalar context; you could expand it to allow returning the remaining list when the iterator is called in list context:

sub foo { # ... wantarray ? @foo : sub { wantarray ? splice @foo : shift @foo } }; }
(It is a little inconsistent to use return in sub foo but not in the anonymous sub.)

Replies are listed 'Best First'.
Re^2: Return a list or an iterator
by Anonymous Monk on Apr 17, 2006 at 18:56 UTC
    The safe way to handle undefs as a valid element is to have the iterator return one element in list context and an empty list if there's no elements, and then always call it in list context when iterating over it.
    my $iter = sub { @foo ? shift @foo : () }; while (my ($elem) = $iter->()) { # $elem may be undefined. }
    This way you don't need it to be an object and you don't need any special end-of-list elements.
Re^2: Return a list or an iterator
by gaal (Parson) on Apr 17, 2006 at 10:29 UTC
    Well, that's a typical semipredicate problem with standard ways to be treated. If you know the kinds of data foo produces are limited, use something else as the break out pattern. Otherwise, signal out of band in some other way (exception on end, have your caller test for "has next"), or use the "unique end ref" trick), with the usual implications of each of those.