Hello Monks,
I'm working with Higher Order Perl and I'm working with the section on iterators. One of the chapters is a function that takes iterators as arguments and when one iterator runs out of values the function returns the next iterator.
I understand the code, but I'm getting some odd results. most of the time, append returns the next iterator, but sometimes it returns a reference to the iterator. for instance, I have to call $it6->()->() to get the second iterator in "Invalid append 4" below.
Why does the append seem to behave differently under seemingly similar circumstances?
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Deparse = 1;
# syntactic sugar
sub NEXTVAL { $_[0]->() }
sub Iterator (&) { return $_[0] }
# turn list into iterator
sub list_iterator { my @list = @_; return Iterator { shift @list } }
# create iterator that returns values from $a to $b
sub upto {
my $start = shift;
my $end = shift;
return Iterator {
return $start <= $end ? $start++ : undef ;
};
}
# append iterators together
sub append {
my @its = @_;
return Iterator {
while (@its) {
my $val = NEXTVAL $its[0];
return $val if defined $val;
shift @its;
}
return;
};
}
# helper function to print iterator values
sub print_it {
my $it = shift;
while (my $var = NEXTVAL $it) {
print Dumper $var;
}
}
print "Valid append 1\n";
my $it1 = append upto(1,3), upto(5,7), upto(9,10);
print_it $it1;
print "\n\nValid append 2\n";
my $ita = list_iterator qw(foo bar baz);
my $itb = list_iterator qw(zab rab oof);
my $itc = upto(1,3);
my $it2 = append $ita, $itb, $itc;
print_it $it2;
print "\n\nInvalid append 1\n";
my $it3 = append upto(1,3), list_iterator qw(foo bar baz), upto (7,9);
print_it $it3;
print "\n\nInvalid append 2\n";
my $it4 = append list_iterator qw(foo bar baz), upto(1,3), upto(7,9);
print_it $it4;
print "\n\nInvalid append 3\n";
my $it5 = append list_iterator qw(foo bar baz), list_iterator qw( a b
+c );
print_it $it5;
print "\n\nInvalid append 4\n";
my $it6 = append list_iterator qw(foo bar baz), list_iterator qw( a b
+c );
$it6->(); $it6->(); $it6->();
# prints "a"
print $it6->()->() . "\n";
Sample output
Valid append 1
$VAR1 = 1;
$VAR1 = 2;
$VAR1 = 3;
$VAR1 = 5;
$VAR1 = 6;
$VAR1 = 7;
$VAR1 = 9;
$VAR1 = 10;
Valid append 2
$VAR1 = 'foo';
$VAR1 = 'bar';
$VAR1 = 'baz';
$VAR1 = 'zab';
$VAR1 = 'rab';
$VAR1 = 'oof';
$VAR1 = 1;
$VAR1 = 2;
$VAR1 = 3;
Invalid append 1
$VAR1 = 1;
$VAR1 = 2;
$VAR1 = 3;
$VAR1 = 'foo';
$VAR1 = 'bar';
$VAR1 = 'baz';
$VAR1 = sub {
use warnings;
use strict 'refs';
return $start <= $end ? $start++ : undef;
};
Invalid append 2
$VAR1 = 'foo';
$VAR1 = 'bar';
$VAR1 = 'baz';
$VAR1 = sub {
use warnings;
use strict 'refs';
return $start <= $end ? $start++ : undef;
};
$VAR1 = sub {
use warnings;
use strict 'refs';
return $start <= $end ? $start++ : undef;
};
Invalid append 3
$VAR1 = 'foo';
$VAR1 = 'bar';
$VAR1 = 'baz';
$VAR1 = sub {
use warnings;
use strict 'refs';
shift @list;
};
Invalid append 4
a
What gives?
Thanks for the assistance.
I've created a gist so you can download and run the code easier: https://gist.github.com/three18ti/7285070
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.