Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

[Solved][HOP] Working with Iterators, why do I suddenly get a coderef?

by three18ti (Scribe)
on Nov 03, 2013 at 00:29 UTC ( #1060998=perlquestion: print w/ replies, xml ) Need Help??
three18ti has asked for the wisdom of the Perl Monks concerning the following question:

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

Comment on [Solved][HOP] Working with Iterators, why do I suddenly get a coderef?
Select or Download Code
Replies are listed 'Best First'.
Re: [HOP] Working with Iterators, why do I suddenly get a coderef?
by LanX (Canon) on Nov 03, 2013 at 00:42 UTC
    I'd suggest to use parens when calling list_iterator()

    Sorry can't test while mobile...

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      Hey Rolf,

      Thanks, you nailed it! I was reading the parenthesis around qw() and thinking that was the parenthesis for the sub call, but it's not, it's the parenthesis around the list.

Re: [HOP] Working with Iterators, why do I suddenly get a coderef?
by choroba (Canon) on Nov 03, 2013 at 00:42 UTC
    I am not sure I understand the question, but adding more parentheses might change the results you get. You can use B::Deparse (used by Data::Dumper in your code, anyway) to see how Perl adds the parentheses to your code. For example, in "Invalid append 1", the following line
    my $it3 = append(upto(1,3), list_iterator( qw(foo bar baz)), upto (7,9 +));

    changes the output to

    Invalid append 1 $VAR1 = 1; $VAR1 = 2; $VAR1 = 3; $VAR1 = 'foo'; $VAR1 = 'bar'; $VAR1 = 'baz'; $VAR1 = 7; $VAR1 = 8; $VAR1 = 9;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Hello,

      Thanks for your reply. Interestingly, I'm not getting a different result when adding parenthisis for the append() call, but when I use parenthesis for the call to list_iterator, it DOES fix my problem.

      my $it3 = append (upto(1,3), list_iterator qw(foo bar baz), upto (7,9) +); print_it $it3;

      prints:

      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; };

      But when I use parenthesis around list_iterator:

      print "\n\nInvalid append 1\n"; my $it3 = append upto(1,3), list_iterator (qw(foo bar baz)), upto (7,9 +); print_it $it3;

      I get what I would expect

      Invalid append 1 $VAR1 = 1; $VAR1 = 2; $VAR1 = 3; $VAR1 = 'foo'; $VAR1 = 'bar'; $VAR1 = 'baz'; $VAR1 = 7; $VAR1 = 8; $VAR1 = 9;

      Thanks for the assist! I think the problem is trying to make too many calls to subs without parenthesis.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1060998]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (10)
As of 2015-07-31 19:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (280 votes), past polls