开发者

Did Perl 5.10 mess something up with prototypes?

I know this type of thing I want to do used to work in 5.8. Am I doing something wrong? Is there a way to get back there in Perl 5.10?

Here's the module:

package TableMod;
use base qw<Exporter>;
our @EXPORT_OK = qw<mod_table>;

use Data::Dumper;
sub mod_table (\%@) { print Dumper( @_ ); }

1;

And here is the script:

use strict;
use warnings;
use Data::Dumper;
use Test::More tests => 4;

sub mod_table_here (\%@) { 
    print Dumper( @_ );
}

use_ok( 'TableMod', 'mod_table' );
can_ok( __PACKAGE__, 'mod_table' );
is( prototype( \&mod_table_here ), '\\%@'
  , q/prototype( \&mod_table_here ) = '\%@'/ 
  );
is( prototype( \&mod_table ), prototype( \&mod_table_here )
   , 'prototypes ARE the SAME!' 
   );
my %table = qw<One 1>;
mod_table_here %table => ( 1, 2, 3, 4 );
#mod_table %table => ( 1, 2, 3, 4 );
mod_table( %table, 1, 2, 3, 4 );

All I have to do is uncomment the next to last line and I get:

Useless use of modulus (%) in void context at - line 17.
Useless use of a constant in void context at - line 17.
Useless use of a constant in void context at - line 17.
Useless use of a constant in void context at - line 17.
Bareword "mod_table" not allowed while "strict subs" in use at - line 17.

It doesn't complain about the local sub, but it loses its mind over the imported one. On top of that despite the tests telling me that I've imported 'mod_table', strict is now confused that it is a bareword!

Not only that but despite the tests telling m开发者_Go百科e that the prototypes are the same, I can't pass %table as a hashref to the imported sub. Not even if I use the conventional syntax, shown in the last line.

What I get is:

1..4
ok 1 - use TableMod;
ok 2 - main->can('mod_table')
ok 3 - prototype( \&mod_table_here ) = '\%@'
ok 4 - prototypes ARE the SAME!
$VAR1 = {
          'One' => '1'
        };
$VAR2 = 1;
$VAR3 = 2;
$VAR4 = 3;
$VAR5 = 4;
$VAR1 = 'One';
$VAR2 = '1';
$VAR3 = 1;
$VAR4 = 2;
$VAR5 = 3;
$VAR6 = 4;


Its because use_ok is being called at run-time. If you add the following then it all works fine:

 use TableMod 'mod_table';

I normally only keep a single test file with use_ok in (normally 00-load.t or 00-use.t). I think Ovid may have written a blog post about this being a good practice?

Update: Found Ovid's blog post I was referring to.

/I3az/


This is the expected result. The use_ok call is at run-time, so the mod_table sub is only compiled and imported after the "call" to it is encountered during compilation, so the "call" to mod_table is interpreted as an illegal bareword.

This code produces the same warnings/error, both on 5.8 and 5.10.

perl -e'use strict; use warnings; my %table; mod_table %table => (1,2,3,4)'

Because the lack of compile-time import can affect the compiled test code in ways like this, it's a good idea to use use instead of use_ok in all tests except a test dedicated to just doing the use_ok (potentially with a BAIL_OUT). (Putting the use_ok in a BEGIN block alleviates these kind of problems but can cause other problems, so isn't a good idea.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜