当一个参数重载字符串化时,为什么`eq`不起作用?

时间:2014-05-01 11:51:36

标签: perl operator-overloading stringification

我已经意识到(艰难的方法)当一个操作数是一个带有重载字符串化的对象时,运算符eq会给出一个致命的运行时错误。

这是一个最小的例子:

my $test = MyTest->new('test');
print 'yes' if $test eq 'test';

package MyTest;

use overload '""' => sub { my $self = shift; return $self->{'str'} };

sub new {
    my ( $class, $str ) = @_;
    return bless { str => $str }, $class;
}

运行它的结果是:

Operation "eq": no method found,
    left argument in overloaded package MyTest,
    right argument has no overloaded magic at ./test.pl line 7.

我对阅读perlop的期望是两个操作数都强制使用字符串上下文,触发$test中的字符串化方法,然后比较结果字符串。为什么它不起作用?实际上是什么?

我遇到此问题的上下文是在同时使用autodieTry::Tiny的脚本中。在try块中,我die包含一些特定的消息。但是在catch块中,当我测试是否$_ eq "my specific message\n"时,如果$_autodie::exception,则会给出运行时。

我知道我必须用$_ eq "..."替换!ref && $_ eq "...",但我想知道原因。

1 个答案:

答案 0 :(得分:21)

您只重载了字符串化,而不是字符串比较。但是,如果您指定overload参数,则fallback => 1 pragma将使用重载的字符串进行字符串比较:

my $test = MyTest->new('test');
print 'yes' if $test eq 'test';

package MyTest;

use overload
    fallback => 1,
    '""' => sub { my $self = shift; return $self->{'str'} };

sub new {
    my ( $class, $str ) = @_;
    return bless { str => $str }, $class;
}

有关其原因的详细信息:

当递交重载对象时,eq运算符将尝试调用eq重载。我们没有提供重载,并且我们没有提供cmp重载,eq可以自动生成。因此,Perl会发出该错误。

使用fallback => 1 enabled,错误被抑制,Perl将执行它无论如何会做的事情 - 强制字符串的参数(调用字符串化重载或其他魔法),并比较它们。