如何在非 class 包中重载运算符?

How to overload operator in non-class package?

在我的情况下,比较字符串相等时不需要警告 Use of uninitialized value in string。所以我认为用 no warnings 'uninitialized' 消除范围内的所有此类警告会更好地用我自己的子例程重载 eq-operator,例如:

use overload 'eq' => \&undefined_equal;

sub undefined_equal {
  my ( $left, $right ) = @_;
  no warnings 'uninitialized';

  if ( $left eq $right ) {
    return 1;
  }
  return 0;
}

当然,overloading 不起作用,因为根据文档,overload 旨在与 类 一起使用,但我有简单的程序包。

所以我确实尝试过重载内置函数,例如:

package REeq;
use strict; use warnings; use 5.014;

BEGIN {
  use Exporter ();
  @REeq::ISA         = qw( Exporter );
  @REeq::EXPORT      = qw( eq );
}

sub eq {
  my ( $left, $right ) = @_;
  no warnings 'uninitialized';

  if ( $left CORE::eq $right ) {
    return 1;
  }
  return 0;
}
1;

我可以调用我的 eq 但不能将其用作接线员。

我需要它,因为我想要它

if ( defined $some_scalar && $some_scalar eq 'literal string' ){
....
}

只使用

if ( $some_scalar eq 'literal string' ){
....
}

我怎样才能实现我的目标?

看来你可以 - 我没试过但是 the perl monks have

sure, if you see it that way... you just have to bless your variable, just like you did with your Number-package.

use overload ...;
my $n = bless {number => 23}, "main";
print $n >> 2;

i think that's not what you want, just wanted to make clear that it's not a problem of the package name but that you must have a blessed object.


编辑:采用 zdim 的板载...

use strict;
use warnings;
use overload 'eq' => \&undefined_equal;

sub undefined_equal {
  my ( $left, $right ) = @_;
  no warnings 'uninitialized';

  if ( ${$left} eq $right ) {
    return 1;
  }
  return 0;
}

my $a = "abcde";
my $n = bless $a, "main";


print "a eq undef -->";
print $a eq undef;

print "<--\nn eq undef -->";
print $n eq undef;
print "<--\n";

这给出了

$ perl overload.pl
Use of uninitialized value in string eq at overload.pl line 20.
a eq undef --><--
n eq undef -->0<--

不要忘记 sub 中的双 $$ 否则你会消失在递归中。而标量引用为bless因为你只能祝福引用,好像

它仍然有一个 bless 但是嘿

改变 eq 的行为是可能的,但它需要编写一个 XS 模块来创建一个操作检查器来替换 perl 为范围内的 eq 操作执行的代码。这是 no autovivification; 使用的方法,例如。