This and other RFCs are available on the web at
http://dev.perl.org/rfc/
=head1 TITLE
Builtin: lazy
=head1 VERSION
Maintainer: David Nicol <[EMAIL PROTECTED]>
Date: 17 Aug 2000
Version: 1
Mailing List: [EMAIL PROTECTED]
Number: 123
=head1 ABSTRACT
C<lazy> is suggested as a keyword to modify an array context
as described in RFC24, "semi-finite (lazy) lists." C<?> will
also work, when it is clear that we're not doing a trinary if.
Also it will work with a block to create an array by subsequent
calls to the block.
=head1 DESCRIPTION
Rather than indicating that lazy evaluation is required by the
addition of incomprehensible syntactic hints, a "lazy array context"
is indicated by the presence of the new keyword C<lazy>.
=head2 why a keyword is needed
tie %h A_DATABASE_RETURNING_OBJECTS, yadda, yadda, yadda;
for (grep {$h{$_}->STATE eq 'NY'} keys %h){
$h{$_}->send_advertisement();
};
We would like "keys" to return an RFC24 "lazy list" when it is
compiler-obvious that it is safe to do so, meaning:
=over
=item
the argument hash is never part of an L-value within
the scope where the return value will be used
=item
the context is marked as accepting lazy lists ?
=item
the argument hash is never part of an L-value within a side effect
=item
the hash is marked iterator-safe, meaning that it is
not vulnerable to deadlocks during iteration.
=back
The question is, how do we tell the compiler that "for" in this
example requires a complete list, because the C<send_advertisement>
method changes the value of its instance?
Do all class methods start marking themselves as to whether they
change their obejcts or not? This seems too complex, and very
likely impossible to automate effectively at this time.
=head2 make lazy keys the programmer's responsibility
What if adding laziness to a list context was up to the programmer
and passed through functions that can support it:
for (lazy(grep {$h{$_}->STATE eq 'NY'} keys %h)){
$h{$_}->send_advertisement();
};
would cause a lazy list is passed to C<for>, and increment of
the object's "letters_sent_total" field might break the iteration.
for (grep {$h{$_}->STATE eq 'NY'} lazy(keys %h)){
$h{$_}->send_advertisement();
};
causes a lazy list to be passed to our filter function C<grep>, saving
us from allocating the entire C<keys> array. C<Grep> is still in
the default busy context, so it returns a busy array, which C<for>
can iterate over safely.
=head2 another use
Another use of C<lazy> would be in defining a lazy array in the first place,
as opposed to wanting to evaluate a subroutine.
@naturals = lazy { my $x=1; yield $x++ };
alternately
@naturals = ? { my $x=1; yield $x++ };
After this assignment, C<shift @naturals> will produce ever-increasing
integers. The state of the subroutine can be reset with C<reset @naturals>.
=head1 IMPLEMENTATION
"Array context" splits into "lazy array context" and "busy array context"
which is the default with which we are all familiar. Functions capable
of returning lazy arrays (or which have been overloaded with homonymous
functions that return lazy arrays, given overloading by context) return lazy arrays
into a lazy array
context.
A lazy array evaluated in a busy array context becomes a busy array, so
if there is no great loss in efficiency a lazy implementation, being more
flexible, is preferred.
If it becomes possible to identify lazy situations without a keyword, of
course the optimizer is welcome to go for it.
The stuff about blocks amounts to a wrapper that creates a package
with a unique name and ties the lvalue to it.
=head1 impact on legacy code
Hardly any. $lazy, @lazy, %lazy are not affected.
=head1 REFERENCES
RFC24 semi-finite (lazy) lists
RFC31 Co-routines (Conway)
Tom Hughes pointed out the problem with hash iterators