I have realised (the hard way) that operator eq
gives a fatal runtime error when one of the operand is an object with overloaded stringification.
Here is a minimal example:
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;
}
The result of running this is:
Operation "eq": no method found,
left argument in overloaded package MyTest,
right argument has no overloaded magic at ./test.pl line 7.
My expectation from reading perlop would be that string context is forced on both operands, firing the stringification method in $test
, then the resulting strings are compared. Why doesn't it work? What is actually hapenning?
The context in which I had this problem was in a script that uses both autodie
and Try::Tiny
. In the try
block, I die
with some specific messages to be caught. But in the catch
block, when I test for whether $_ eq "my specific message\n"
, this gives a runtime if $_
is an autodie::exception
.
I know I will have to replace $_ eq "..."
with !ref && $_ eq "..."
, but I would like to know why.
You only overloaded stringification, not string comparison. The overload
pragma will however use the overloaded stringification for the string comparison if you specify the fallback => 1
parameter:
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;
}
Details on why this works:
When handed an overloaded object, the eq
operator will try to invoke the eq
overload. We did not provide an overload, and we didn't provide a cmp
overload from which eq
could be autogenerated. Therefore, Perl will issue that error.
With fallback => 1
enabled, the error is suppressed and Perl will do what it would do anyway – coerce the arguments to strings (which invokes stringification overloading or other magic), and compare them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With