Perl Path::Class::file with "use constant" 给出祝福的引用,而不是字符串 - 为什么?



在 Ubuntu 14.04 LTS 上运行 Perl 5.18,我想创建一些路径名常量,所以我做了

use Path::Class;
use constant FILEPATH => file('directory', 'filename');

但是,当我开始在哈希聚合中使用常量时......

my $hash = { filepath => FILEPATH };
use Data::Dumper;
print Dumper $href;

。我惊讶地发现filepath键的值是一个祝福的引用,而不是我期望的函数调用的字符串结果。

我可以像这样解决问题...

use constant FILEPATH => file('directory', 'filename') . "";

。这迫使 Perl 解释器评估祝福的引用,但是

(a( 有没有更好的办法,以及 (b( 这到底是怎么回事?!

我知道use constant是在列表上下文中评估的,但通常use constant MYCONST => mysub(arg1, arg2);做正确的事情,评估子例程调用并使用返回值。Path::Class::file的聪明之处是什么打破了这种期望?

模块 Path::Class中的file函数实际上是 Path::Class 对象的构造函数。它始终返回一个对象。甚至概要也是这么说的。

use Path::Class;
my $dir  = dir('foo', 'bar');       # Path::Class::Dir object
my $file = file('bob', 'file.txt'); # Path::Class::File object

如果您只需要路径,请在返回值file上调用该方法,并将该调用的返回值分配给常量。你得到的对象是一个 Path::Class::File。它提供了多种方法。若要执行与使用字符串重载时相同的操作,请调用stringify方法。

use constant FILEPATH => file('directory', 'filename')->stringify;

HTML::Tiny 的相关部分根据输入的类型决定做什么。它需要undef,字符串或数组引用,但您提供的内容都不是这些。换句话说,这是GIGO的一个案例。您正在使用file()返回的值,这是一个重载字符串化的对象。

使用以下任一方法提供预期的输入:

use constant FILEPATH => file('directory', 'filename')->stringify;

use constant FILEPATH => "".file('directory', 'filename');

请注意,将对象用作常量通常是不安全的,因为它们不是常量。但是,由于file()返回一个不可变的对象,因此将其用作常量并没有什么坏处,因为它确实是常量。

你对返回对象的 Path::Class::file 的看法是正确的。 这就是 Dumper 输出中所有"祝福"的东西。 对不起,我没有早点意识到这一点。

正如您将从我的评论中看到的那样,我在使用HTML::Tiny时遇到了问题,您可以看到如下:-

$ perl -MPath::Class -MHTML::Tiny -le 'print HTML::Tiny->new(mode=>"html")->form({action=>file("cgi-bin", "script")})'
<form action></form>

如您所见,action属性缺少路径。 然而

$ perl -MPath::Class -MHTML::Tiny -le 'print HTML::Tiny->new(mode=>"html")->form({action=>file("cgi", "script").""})'
<form action="cgi/script"></form>

这是因为.""字符串串联运算符会导致调用 Class::P ath::File 对象的自动字符串,因此在{action=>value}哈希中传递实际字符串,而不是对象。

如果你深入研究 HTML::Tiny 1.05 代码,你会发现sub _tag在第 622 行,它

if ( ref $val ) {
return $attr if not $self->_xml_mode;

此测试允许您使用{ attr=>[] }输出不带值的属性名称,但不幸的是,如果$val是一个对象,则测试也是 TRUE。 我将针对 HTML::Tiny 提出一个错误报告。

最新更新