是否有可能不涉及通过 B::Deparse
或其他任何方式将有问题的子例程解析回其源形式?手头的任务是当一个属性(通过 package Foo;sub x :ATTR(...); ... sub x { ... }
)应用于它时,要知道一个特定的子程序引用是否指向一个没有实际主体的预先声明的子程序(如 Attribute::Handlers
)。起初我以为在这种情况下 $code
参数将是未定义的,但事实证明并非如此。虽然 deparsing 可用于此任务,因为此类子例程仅返回 ';'
作为其通过 B::Deparse
反编译的代码,将其用于大型函数有其考虑因素,以及跨所有 Perl 版本、使用的模块等对该输出的依赖等不漂亮。
最佳答案
我想我已经找到了一个没有解析或大小测试的解决方案。使用B模块,我可以查询
my $cv=B::svref_2object($code);
undef $code if ref $cv->START eq 'B::NULL';
其中
if ref $cv->START eq 'B::NULL'
在我公认的有限测试中,仅在仅预先声明 sub 时才为真。它甚至可以过滤掉没有像 sub x{}
这样的语句的 subs,这完全符合我的要求,与以前的解决方案不同。我对此的唯一提示是不同 Perl 版本之间可能存在差异,但我还找不到此类信息;无论如何,我大部分时间都坚持我当前的版本。我通过盲目猜测找到了它,我被 Chromatic、Damian Conway 和 Curtis Poe (link) 合着的一本名为“Perl Hacks: Tips & Tools for Programming, Debugging, and Surviving”的书指出了正确的方向。它描述了如何在模块中找到最大的子程序。所以我希望重写代码,只获取给定子程序的大小,但是代码太重,无法在项目中使用,包括另一个CPAN模块依赖。所以我寻找了另一种选择,摆弄着 CPAN
B::TerseSize
模块,直到我发现他们几乎都以一种或另一种方式使用 B
来做他们的事情。但是查看 B
模块的文档是一件苦差事。长话短说,在疯狂打印各种 START
方法的返回值之后,我只是猜测 CV
是我最终要寻找的东西。关于perl - 用最少的代码区分空子程序和子程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40562885/