I don't understand the error message
Type of argument to each on reference must be unblessed hashref or arrayref at test.pl line 17.
for this test case (extracted from a larger module):
BEGIN { our $RE_timestamp = qr/whatever/; }
# check Regular expressions for TIMESTAMP
use constant _TEST_TIMESTAMPS => ( # from "6.2.3.1. Examples"
'1985-04-12T23:20:50.52Z' => 1,
'1985-04-12T19:20:50.52-04:00' => 1,
'2003-10-11T22:14:15.003Z' => 1,
'2003-08-24T05:14:15.000003-07:00' => 1,
'2003-08-24T05:14:15.000000003-07:00' => 0, # invalid!
'-' => 1 # NILVALUE
);
UNITCHECK
{
# from "6.2.3.1. Examples"
while (my ($str, $valid) = each _TEST_TIMESTAMPS) {
if ($valid) {
die "timestamp ($str) is not valid\n"
if ($str !~ /^${RE_timestamp}$/o);
} else {
die "timestamp ($str) is valid\n"
if ($str =~ /^${RE_timestamp}$/o);
}
}
}
Most of all I got the error in Perl 5.18.2, but when I checked on another machine using Perl 5.26.1, there was no error message at all!
So can I make the code work with the older Perl 5.18, too?
Ugly Work-Around
Experimenting I found out that each (my %h = _TEST_TIMESTAMPS)
did not help, but when using my %h = _TEST_TIMESTAMPS;
and then each %h
, then the error was gone.
Still I don't understand what's going on (before using constants I had local my
hashes used inside UNITCHECK
.
Obviously I'd like to use package-level constants instead.
CodePudding user response:
The constant produced by the constant pragma is really a subroutine ("in the current implementation", as docs say. (See Technical Notes
and Bugs
.) Thus, I guess, they aren't what the error message says is required, hashref (unblessed) or arrayref.
Swapping the const
for, say, Const::Fast
, seems to confirm this since it then works
use warnings;
#use strict; # for undeclared $RE_timestamp used in regex (typos)
use feature 'say';
use Const::Fast;
BEGIN { our $RE_RE_timestamp = qr/whatever/; }
# check Regular expressions for TIMESTAMP
BEGIN {
const our %_TEST_TIMESTAMPS => ( # from "6.2.3.1. Examples"
'1985-04-12T23:20:50.52Z' => 1,
'1985-04-12T19:20:50.52-04:00' => 1,
'2003-10-11T22:14:15.003Z' => 1,
'2003-08-24T05:14:15.000003-07:00' => 1,
'2003-08-24T05:14:15.000000003-07:00' => 0, # invalid!
'-' => 1 # NILVALUE
);
}
UNITCHECK
{
say "$_ => $_TEST_TIMESTAMPS{$_}" for keys %_TEST_TIMESTAMPS;
# from "6.2.3.1. Examples"
while (my ($str, $valid) = each %_TEST_TIMESTAMPS) {
if ($valid) {
die "timestamp ($str) is not valid\n"
if ($str !~ /^${RE_timestamp}$/o);
} else {
die "timestamp ($str) is valid\n"
if ($str =~ /^${RE_timestamp}$/o);
}
Lexicals introduced with Const::Fast
must be assigned at declaration (and of course cannot be reassigned later) so that has to be an our
variable (unfortunately in my book) since it need be in a BEGIN
block.
This does work.
As for why this isn't an issue in later Perls, I suppose that the requirement for it to be a hashref or arrayref got dropped at some point. (I can't check that right now.)
Note that you have a typo, declaring $RE_RE_timestamp
but using $RE_timestamp
.
CodePudding user response:
Try to unbless _TEST_TIMESTAMPS like below before calling each:
use Data::Structure::Util qw(unbless);
unbless(_TEST_TIMESTAMPS);