当函数my_func()已导出但未定义时,为什么*main::my_func{CODE}*是coderef



我有一个项目,我重命名了一个Perl模块,因为它的名称太通用,并且写了一个小的兼容性模块。我甚至为兼容性模块写了一个测试,但它是假阳性。为什么这感觉很难测试如果因为副作用而无法调用导出函数,如何实际测试导出函数的存在

在我的兼容性模块中,我继承了新模块,但没有导入它的功能。令我惊讶的是,这还不够。在这里,我构建了一个只涉及一个包的最小示例:

use strict;
use warnings;
use feature qw(say);
{
package MyPackage;
use parent 'Exporter';
our @EXPORT = qw(foo);
}
MyPackage->import();
say *main::foo{CODE};
say *MyPackage::foo{CODE};
say main->can('foo');
say MyPackage->can('foo');
foo();

(我用MyPackage->import()替换了use MyPackage,使这个例子在1个文件中工作。(

输出:

CODE(0x55fa5cf9e750)
CODE(0x55fa5cf9e750)
CODE(0x55fa5cf9e750)
CODE(0x55fa5cf9e750)
Undefined subroutine &MyPackage::foo called at inherit.pl line 16.

这一切看起来像是函数存在,但当我试图调用它时它失败了。

这是Perl 5.34。

更新以回答zdim的问题:实际问题是什么

我将实际代码从OldModule.pm移到了NewModule.pm(当然不是他们的真名(,并创建了一个新的OldModule.pm,以与使用它的现有软件兼容。实际的代码通过import()提供了包函数以及类和对象方法。所以我使用了use parent 'NewModule'来继承它们。我相信这也会继承包函数。我使用Test2的can_ok进行的测试错误地表明它有效。

多亏了一位同事的错误报告,我了解到这还不够,并发现我还需要导入包函数。

我不能简单地调用有问题的函数来测试兼容性包,因为这是CGI应用程序的一部分,函数实际上会执行数据库操作或将内容打印到STDOUT,并会污染我的TAP输出。(是的,我的部分任务当然是摆脱CGI。(

package OldPackage;
# ABSTRACT: transitional package for new name NewPackage
use strict;
use warnings;
use NewPackage;  # this is the line I added to fix the issue
use Exporter qw(import);
our @EXPORT = @NewPackage::EXPORT;   # this line only declared undefined functions
1;

Exporter实际上做了类似的事情:

*main::foo = &MyPackage::foo;

就像标量、数组和散列一样,引用子可以使符号生动起来。具体来说,它创建了一个未定义的子,就像您执行了sub foo;一样。

$ perl -M5.010 -e'
&foo;    say *foo{CODE};
sub bar;  say *bar{CODE};
'
CODE(0x55da28044470)
CODE(0x55da28073750)

exists(&f)检查它是否存在,defined(&f)检查它是否已定义。

$ perl -M5.010 -e'
sub foo { }
sub bar;

for (qw( foo bar baz )) {
say exists(  &$_ ) ? "$_ exists"     : "$_ doesnx27t exist";
say defined( &$_ ) ? "$_ is defined" : "$_ isnx27t defined";
}
'
foo exists
foo is defined
bar exists
bar isn't defined
baz doesn't exist
baz isn't defined

相关内容

最新更新