1
votes

I have the following code in in a Perl script I'm writing:

#!/usr/bin/perl
use DBI;
use Getopt::Long;
use Time::HiRes;
use Error qw(:try);

....

my $starttime = Time::HiRes::time;

try {
    my $dbh = DBI->connect("dbi:Sybase:$server", $username, $password);
    $dbh->do("use $database");
    my $query="exec OfflineDatabaseReport";

    $row = $dbh->selectrow_hashref($query);

    $dbh->disconnect();
} catch Error with {
    print "boom";
    exit 1;
};
my $endtime = Time::HiRes::time;
my $timetaken = $endtime - $starttime;

The script worked fine until I wrapped the data access portion in the try...catch block. Now I get the following exception thrown:

Can't use string ("1316135985.90893") as a HASH ref while "strict refs" in use at /usr/lib/perl5/site_perl/5.8.8/Error.pm line 217.

I did try setting:

no strict "refs";

But I still get the same error. Am I being naive in my usage of a try/catch block here?

1
From the description of that module on CPAN: Using the "Error" module is no longer recommended due to the black-magical nature of its syntactic sugar, which often tends to break. Its maintainers have stopped actively writing code that uses it, and discourage people from doing so. See the "SEE ALSO" section below for better recommendations. search.cpan.org/~shlomif/Error-0.17016/lib/Error.pm - Brian Roach
@brian - ah...that recommendation completely hit my blindspot. Feel free to facepalm. - Kev
Also, don't forget to put a semicolon at the end of the catch {...} block -- that will come back to bite you in the you-know-where. - mob
For your information, since this question was posted, there is now a perfect implementation of try-catch in perl with Nice::Try - Jacques
@Jacques thanks for the info. I haven't touched Perl for a long time now, but will keep in mind. - Kev

1 Answers

3
votes

This is how the parser sees the code:

try({ ... }, catch(Error, with({ ... }, my $endtime = Time::HiRes::time)));

Meaning, it passes the result of setting $endtime to Time::HiRes::time as the 2nd argument of the with BLOCK sub. Looking at the source of Error.pm, I see:

sub with (&;$) {
    @_
}

Which means with BLOCK,SCALAR is a valid argument list. All it does is pass the arguments up to catch, which interprets my $endtime = Time::HiRes::time as its $clauses. catch itself returns $clauses, which turns the whole statement into:

try({ ... }, my $endtime = Time::HiRes::time);

try assumes $clauses is a hashref, as you can see by the call to

$clauses->{'finally'}->()
    if(defined($clauses->{'finally'}));

So perl tries to use the value of Time::HiRes::time as a hashref, which it most certainly cannot, since it's actually a scalar with a value of "1316135985.90893".

So yeah, the semicolon at the end of the catch block.