在 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 提出一个错误报告。