Perl 5.10 是不是把原型弄乱了?

Posted

技术标签:

【中文标题】Perl 5.10 是不是把原型弄乱了?【英文标题】:Did Perl 5.10 mess something up with prototypes?Perl 5.10 是否把原型弄乱了? 【发布时间】:2010-12-31 06:31:41 【问题描述】:

知道这种我想做的事情曾经在 5.8 中工作过。难道我做错了什么?有没有办法在 Perl 5.10 中回到那里?

这是模块:

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

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

1;

这是脚本:

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

我所要做的就是取消对最后一行的注释,然后我得到:

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.

它不抱怨本地潜艇,但它对进口的潜艇失去了理智。最重要的是,尽管测试告诉我我已经导入了“mod_table”,但现在严格感到困惑的是它是一个裸词!

不仅如此,尽管测试告诉我原型是相同的,但我不能%table 作为 hashref 传递给导入的 sub。即使我使用最后一行所示的常规语法也不行。

我得到的是:

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;

【问题讨论】:

添加了(_)原型,但我认为没有关系。 【参考方案1】:

这是因为use_ok 在运行时被调用。如果您添加以下内容,则一切正常:

 use TableMod 'mod_table';

我通常只保留一个带有use_ok 的测试文件(通常是00-load.t00-use.t)。我认为 Ovid 可能已经写了一篇关于这是一个好的做法的博客文章?

更新:找到Ovid's blog post我指的是。

/I3az/

【讨论】:

不是5.10.*自带的use_ok(),是所有版本的use_ok()都有问题。如果您在 Perl 解析源代码的其余部分之前不加载模块,您将无法获得原型或导入的好处。 @brian - 绝对正确。当我使用 5.8.8 进行快速测试时,OP 代码确实有效,但我现在不能重复这一点,所以我在做这件事时搞砸了一些东西;-( 我已经相应地修改了答案。【参考方案2】:

这是预期的结果。 use_ok 调用是在运行时调用的,因此 mod_table sub 仅在编译过程中遇到对其的“调用”之后编译和导入,因此对 mod_table 的“调用”被解释为非法裸字.

此代码在 5.8 和 5.10 上产生相同的警告/错误。

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

因为缺少编译时导入会以多种方式影响已编译的测试代码 像这样,在所有测试中使用 use 而不是 use_ok 是个好主意,除了 a 专门用于执行 use_ok 的测试(可能使用BAIL_OUT)。 (将 use_ok 放在 BEGIN 块中可以缓解这类问题,但可能会导致 其他问题,所以不是一个好主意。)

【讨论】:

以上是关于Perl 5.10 是不是把原型弄乱了?的主要内容,如果未能解决你的问题,请参考以下文章

自动布局弄乱了我的动画

为啥 QTextBrowser 弄乱了我的 HTML 代码?

实体框架弄乱了行 ID

NSJSONSerialization 弄乱了结果 NSDictionary

RecyclerView 在滚动时弄乱了子视图

UITextField 子类弄乱了adjustFontSizeToWidth