Subject: | [PATCH] delay code call until result is needed (fixes #37492 and #47109) |
This patch delays the call to the user code until the result is needed
to satisfy a value(), is_exhaused() or isnt_exhausted() call.
This eliminates some duplicated code, and fixes #37492 and #47109 - I've
included the test scripts from those tickets, they now pass.
Subject: | Iterator.patch |
diff -Nurd Iterator-0.03-orig/Iterator.pm Iterator-0.03/Iterator.pm
--- Iterator-0.03-orig/Iterator.pm 2005-10-10 06:03:00.000000000 +0200
+++ Iterator-0.03/Iterator.pm 2009-10-05 15:55:50.000000000 +0200
@@ -162,24 +162,6 @@
$code_for {$self} = $code;
- # Get the next (first) value for this iterator
- eval
- {
- $next_value_for{$self} = $code-> ();
- };
-
- my $ex;
- if ($ex = Iterator::X::Am_Now_Exhausted->caught ())
- {
- # Starting off exhausted is okay
- $is_exhausted{$self} = 1;
- }
- elsif ($@)
- {
- Iterator::X::User_Code_Error->throw (message => "$@",
- eval_error => $@);
- }
-
return;
}
@@ -215,13 +197,17 @@
{
my $self = shift;
+ exists $next_value_for{$self} or $self->_fetch;
+
Iterator::X::Exhausted->throw(q{Iterator is exhausted})
if $is_exhausted{$self};
- # The value that we'll be returning this time.
- my $this_value = $next_value_for{$self};
+ return delete $next_value_for{$self};
+ }
+
+ sub _fetch {
+ my $self = shift;
- # Compute the value that we'll return next time
eval
{
$next_value_for{$self} = $code_for{$self}->(@_);
@@ -230,14 +216,13 @@
{
# Aha, we're done; we'll have to stop next time.
$is_exhausted{$self} = 1;
+ $next_value_for{$self} = undef;
}
elsif ($@)
{
Iterator::X::User_Code_Error->throw (message => "$@",
eval_error => $@);
}
-
- return $this_value;
}
# Method name: is_exhausted
@@ -251,7 +236,9 @@
{
my $self = shift;
- return $is_exhausted{$self};
+ exists $next_value_for{$self} or $self->_fetch;
+ return 1 if $is_exhausted{$self};
+ return;
}
# Method name: isnt_exhausted
@@ -265,7 +252,7 @@
{
my $self = shift;
- return ! $is_exhausted{$self};
+ return ! $self->is_exhausted;
}
} # end of encapsulation enclosure
diff -Nurd Iterator-0.03-orig/t/rt37492.t Iterator-0.03/t/rt37492.t
--- Iterator-0.03-orig/t/rt37492.t 1970-01-01 02:00:00.000000000 +0200
+++ Iterator-0.03/t/rt37492.t 2009-10-05 16:10:59.000000000 +0200
@@ -0,0 +1,18 @@
+
+use strict;
+use warnings;
+
+use Iterator;
+use Test::More;
+
+my $value = 0;
+my $foo = Iterator->new( sub { return ++$value } );
+
+plan(tests=>4);
+is($foo->value(),1);
+is($foo->value(),2);
+
+# Reset value we're keying off to something else entirely.
+$value = 20;
+is($foo->value(),21);
+is($foo->value(),22);
diff -Nurd Iterator-0.03-orig/t/rt47109.t Iterator-0.03/t/rt47109.t
--- Iterator-0.03-orig/t/rt47109.t 1970-01-01 02:00:00.000000000 +0200
+++ Iterator-0.03/t/rt47109.t 2009-10-05 16:16:45.000000000 +0200
@@ -0,0 +1,8 @@
+use Test::More tests => 1;
+use Iterator;
+
+my $value = 0;
+
+my $iterator = new Iterator(sub { return ++$value });
+
+is($value, 0, "Haven't called the iterator yet.");
diff -Nurd Iterator-0.03-orig/t/value.t Iterator-0.03/t/value.t
--- Iterator-0.03-orig/t/value.t 2005-10-10 06:03:00.000000000 +0200
+++ Iterator-0.03/t/value.t 2009-10-05 16:04:55.000000000 +0200
@@ -1,5 +1,5 @@
use strict;
-use Test::More tests => 33;
+use Test::More tests => 35;
use Iterator;
# Check that value() works.
@@ -163,6 +163,13 @@
{
$val = $iter->value;
};
+is ($@, q{}, q{User-error iterator; second value no error.});
+cmp_ok ($val, '==', 2, q{User-error iterator; second value correct});
+
+eval
+{
+ $val = $iter->value;
+};
isnt ($@, q{}, q{User-error iterator blew up on time});
$x = $@;
ok (Iterator::X->caught(), q{User-error base exception caught});