首页 > 解决方案 > 为什么有些用户在 Perl 中引用类名?

问题描述

查看Type::Tiny,我看到调用中的类名在Type::Tiny->new官方文档中被引用,

my $NUM = "Type::Tiny"->new(
   name       => "Number",
   constraint => sub { looks_like_number($_) },
   message    => sub { "$_ ain't a number" },
);

为什么是这样?这仅仅是风格吗?这种做法是否有任何性能影响?

标签: perlcoding-styleclassnamebareword

解决方案


举一个更简单的例子

package Foo { sub new { die 7  } };
package Bar { sub new { die 42 } };
sub Foo { "Bar" }
Foo->new();

在上面的示例中,常量Foo解析为“Bar”,因此调用"Bar"->newnot "Foo"->new。你如何阻止子程序解析?你可以引用它。

"Foo"->new();

至于性能影响,使用字符串而不是裸词不会使事情变得更糟。我已经确认生成的 optreeO=Deparse是相同的。因此,作为一般规则,如果您重视正确性,似乎最好引用类名。

这在 Programming Perl 中提到,(遗憾的是在间接方法调用的上下文中)

...所以我们会告诉你,只要有两件事是真的,你几乎总是可以用一个简单的类名逃脱。首先,没有与类同名的子程序。(如果您遵循子例程名称(如以new小写开头)和类名(如以ElvenRing大写开头)的约定,这绝不是问题)。二、类被加载了一个

use ElvenRing;
require ElvenRing;

这些声明中的任何一个都确保 Perl 知道ElvenRing是一个模块名,这会强制new将类名之前的任何裸名ElvenRing解释为方法调用,即使您碰巧new在当前包中声明了自己的子例程。

而且,这是有道理的:只有当您的子例程(通常是小写字母)与类(通常是大写字母)具有相同的名称时,才会发生这种混淆。仅当您违反上述命名约定时,才会发生这种情况。

tldr; 如果你知道它们并且你重视正确性而不是混乱,那么引用你的类名可能是一个好主意。

旁注:或者,您可以通过在函数末尾附加 a::来停止将裸词解析为函数,例如在上面的Foo::->new.


感谢reddit 上的 Ginnz 向我指出这一点,并感谢Toby Inkster 的评论(尽管在第一次阅读时对我来说没有意义)。


推荐阅读