【问题标题】:Why does `eq` not work when one argument has overloaded stringification?当一个参数重载字符串化时,为什么 eq 不起作用?
【发布时间】:2014-06-17 21:29:01
【问题描述】:

我已经意识到(很难)当操作数之一是具有重载字符串化的对象时,运算符 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 "...",但我想知道为什么。

【问题讨论】:

  • 试试"$test" eq 'test'
  • @HunterMcMillen,这行得通,谢谢。但我看不出它对解释器有什么影响!
  • eq 比较实际上并不强制 $test 被字符串化,它只是在其参数上使用字符串比较。

标签: perl operator-overloading stringification


【解决方案1】:

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

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 会做它会做的事情——强制字符串的参数(这会调用字符串化重载或其他魔法),然后比较它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 2020-07-04
    • 2012-11-30
    • 2014-04-19
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    相关资源
    最近更新 更多