Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Learning the High Order Perl: issue with iterator

Tags:

perl

I study the High Order Perl book and have an issue with iterators in the Chapter 4.3.4.

The code:

main_script.pl

#!/perl
use strict;
use warnings;

use FindBin qw($Bin);
use lib $Bin;
use Iterator_Utils qw(:all);
use FlatDB;

my $db = FlatDB->new("$Bin/db.csv") or die "$!";
my $q = $db->query('STATE', 'NY');
while (my $rec = NEXTVAL($q) )
{
     print $rec;
}

Iterator_Utils.pm

#!/perl
use strict;
use warnings;
package Iterator_Utils;
use Exporter 'import';;
our @EXPORT_OK = qw(NEXTVAL Iterator
            append imap igrep
            iterate_function filehandle_iterator list_iterator);
our %EXPORT_TAGS = ('all' => \@EXPORT_OK);
sub NEXTVAL { $_[0]->() }
sub Iterator (&) { return $_[0] }

FlatDB.pm

#!/perl
use strict;
use warnings;

package FlatDB;

my $FIELDSEP = qr/:/;

sub new 
{
    my $class = shift;
    my $file = shift;

    open my $fh, "<", $file or return;
    chomp(my $schema = <$fh>);

    my @field = split $FIELDSEP, $schema;
    my %fieldnum = map { uc $field[$_] => $_ } (0..$#field);
   bless 
   { 
       FH => $fh, 
       FIELDS => \@field, 
       FIELDNUM => \%fieldnum,
       FIELDSEP => $FIELDSEP 
   } => $class;
}

use Fcntl ':seek';
sub query 
{
     my $self = shift;
     my ($field, $value) = @_;
     my $fieldnum = $self->{FIELDNUM}{uc $field};
     return unless defined $fieldnum;
     my $fh = $self->{FH};
     seek $fh, 0, SEEK_SET;
     <$fh>; # discard schema line
     return Iterator 
     {
       local $_;
       while (<$fh>) 
       {
            chomp;
            my @fields = split $self->{FIELDSEP}, $_, -1;
            my $fieldval = $fields[$fieldnum];
            return $_ if $fieldval eq $value;
       }
       return;
    };
 }

db.csv

LASTNAME:FIRSTNAME:CITY:STATE:OWES
Adler:David:New York:NY:157.00
Ashton:Elaine:Boston:MA:0.00
Dominus:Mark:Philadelphia:PA:0.00
Orwant:Jon:Cambridge:MA:26.30
Schwern:Michael:New York:NY:149658.23
Wall:Larry:Mountain View:CA:-372.14

Just as in the book so far, right? However I do not get the output (the strings with Adler and Schwern should occur). The error message is:

 Can't use string ("Adler:David:New York:NY:157.00") as a subroutine ref while 
"strict refs" in use at N:/Perle/Learn/Iterators/Iterator_Utils.pm line 12, <$fh> 
line 3.

What am I doing wrong?

Thanks in advance!

like image 620
v_e Avatar asked Mar 23 '14 14:03

v_e


1 Answers

FlatDB calls Iterator, which is defined in Iterator_Utils, so it needs to import that function from Iterator_Utils. If you add

use Iterator_Utils qw(Iterator);

after package FlatDB, the program will work.

Thanks very much for finding this error. I will add this to the errata on the web site. If you would like to be credited by name, please email me your name.

like image 150
Mark Dominus Avatar answered Sep 19 '22 13:09

Mark Dominus