w.k
w.k

Reputation: 8376

How to overload operator in non-class package?

In my situation I don't need warnings Use of uninitialized value in string while comparing string equality. So I tought that instead silencing all such warnings in the scope with no warnings 'uninitialized' would be better to overload eq-operator with my own subroutine, like:

use overload 'eq' => \&undefined_equal;

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

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

Of course, overloading does not work, because according to the docs, overload is meant to use with classes, but I have plain procedural packages.

So I did try with overloading built-in functions, like:

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;

I can call my eq but can't use it as operator.

I need it because I want instead

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

to use just

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

How could I achieve my goal?

Upvotes: 2

Views: 118

Answers (2)

KeepCalmAndCarryOn
KeepCalmAndCarryOn

Reputation: 9075

Seems you can - I haven't tried this but 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.


Edit: taking zdim's onboard...

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";

which gives

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

Don't forget the double $$ in the sub or you disappear into recursion. And the scalar reference for bless as you can only bless references, it seems

It still has a bless but hey

Upvotes: 0

ikegami
ikegami

Reputation: 385645

Changing the behaviour of eq is possible, but it requires writing an XS modules that creates an op checker that replaces the code perl executes for the eq ops in scope. This is the approach used by no autovivification;, for example.

Upvotes: 2

Related Questions