当前位置: 首页 > 知识库问答 >
问题:

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

申高峰
2023-03-14

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

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

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替换为MyPackage。)-

输出:

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

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

这是Perl 5.34。

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

我将实际代码从OldModule移动。pm新建模块。pm(当然不是他们的真名)并创建了一个新的旧模块。pm与使用该软件的现有软件兼容。实际代码通过import()以及类和对象方法提供了两个包函数。所以我使用了使用父“NewModule”来继承它们。我相信这也会继承包函数。我用Test2的进行的测试可能会错误地显示它工作了。

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

我不能简单地调用有问题的函数来测试兼容性包,因为这是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;

共有1个答案

越英韶
2023-03-14

实际上,出口商做了类似的事情:

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

就像标量、数组和散列一样,引用子元素会使符号生动。具体地说,它会创建一个未定义的sub,就好像你做了sub-foo

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

存在(

$ perl -M5.010 -e'
   sub foo { }
   sub bar;
   
   for (qw( foo bar baz )) {
      say exists(  &$_ ) ? "$_ exists"     : "$_ doesn\x27t exist";
      say defined( &$_ ) ? "$_ is defined" : "$_ isn\x27t defined";
   }
'
foo exists
foo is defined
bar exists
bar isn't defined
baz doesn't exist
baz isn't defined

 类似资料:
  • JSP规范中引入的EL大大简化了JSP页面的开发,使不熟悉Java语言的网页设计人员也可以通过EL表达式在JSP页面中访问很多系统级的资源,以及进行一系列的服务端操作。但EL本身的功能非常有限,为此,EL允许开发人员定义自己的函数来扩展EL的功能。 EL自定义函数实际上就是普通Java类中的方法。但作为EL自定义函数的Java类和方法必须满足如下的条件: l Java类必须被声明成public。

  • 我一直得到这个错误: 致命错误:未捕获错误:调用未定义的函数mysqli_connect()在C:\Apache24\htdocs\asd.php: 2堆栈跟踪:#0{main}抛出在C:\Apache24\htdocs\asd.php在第2行 在任何php文件中运行任何mysqli cmd时,例如: 我已经在php中启用了扩展。ini文件,我一直在努力解决这个问题,但我就是做不到。任何帮助都将不

  • 问题内容: 我正在使用angularjs编写示例应用程序。我在chrome浏览器上遇到以下错误。 错误是 错误:[ng:areq] http://errors.angularjs.org/1.3.0-beta.17/ng/areq?p0=ContactController&p1=not%20a%20function%2C%20got%20undefined 呈现为 参数“ ContactContr

  • 问题内容: 在严格模式下使用javascript时,为什么在匿名函数中未定义此函数?我知道为什么这样做可能有意义,但是我找不到任何具体答案。 例: 问题答案: 这是因为,在ECMAscript 262第5版之前,如果使用的人忘记使用该关键字,那会造成很大的混乱。如果在ES3中调用构造函数时忘了使用,请引用全局对象(在浏览器中),然后用变量破坏全局对象。 这是可怕的行为等人在ECMA决定,只是为了集

  • 问题内容: 我正在使用angularjs编写示例应用程序。我在chrome浏览器上遇到以下错误。 错误是 错误:[ng:areq] http://errors.angularjs.org/1.3.0-beta.17/ng/areq?p0=ContactController&p1=not%20a%20function%2C%20got%20undefined 呈现为 参数“ ContactContr

  • 问题内容: 我正在使用Vue.js创建一个组件。 当我引用中的任何所述的生命周期钩(,,等等)它的计算结果为: 我的计算属性内部也发生了同样的事情: 我收到以下错误: 未捕获的TypeError:无法读取未定义的属性“ bar” 为什么要在这些情况下进行评估? 问题答案: 这两个示例都使用arrow函数,该函数绑定到与Vue实例不同的上下文。 根据文档: 不要在实例属性或回调(例如)上使用箭头功能