http://www.perlmonks.org?node_id=478237

rg0now has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks!

I have been wading through both perltie(1) and overload(3), but I can't seem to find why the snippet below does not work as expected (by me).

What I am trying to do here is to abstract away a very complex XSUB interface consisting of an iterator (here repersented by MyTie) over a C++ class (Dummy in the code below) as a tied array. I want to allow the user to iterate over the classes by a simple foreach. And while doing that, the user should really be able to use the overloaded operators of the Dummy class.
#!/usr/bin/perl package Dummy; use strict; use warnings; use overload '==' => \&iseq; sub new { return bless [ $_[1] ], $_[0];} sub iseq { return $_[0]->[0] == $_[1]->[0] ;} package MyTie; use strict; use warnings; use Carp; our $AUTOLOAD; sub TIEARRAY { my $class = shift; return bless [ map { Dummy->new($_) } @_ ], $class; } sub FETCH { $_[0]->[ $_[1] ]; } sub FETCHSIZE { scalar @{$_[0]}; } sub AUTOLOAD { croak "Undefined method $AUTOLOAD called in " . __PACK +AGE__;} package main; use strict; use warnings; use Data::Dumper; use Devel::Peek; tie my @arr, 'MyTie', 1,3,4; for my $i (@arr){ for my $j (@arr){ # uncomment this row and comment out the next one, and it works # if($i->iseq($j)){ if($i == $j){ print $i->[0] . " == " . $j->[0] . "\n"; } else { print $i->[0] . " != " . $j->[0] . "\n"; } } } exit 0;
Curiously, I get the error:
Operation `0+': no method found, argument in overloaded package Dummy +at 5perltie.pl line 42.
So Perl wants to force one of the arguments in ($i == $j) into numeric context. If I add the 0+ overloaded operator:
use overload '==' => \&iseq, '0+' => \# ... sub num { print "Someone wants me (" . $_[0]->[0] . ") in numeric con +text\n"; }
this is what I get:
Someone wants me (1) in numeric context Someone wants me (1) in numeric context 1 == 1 1 != 3 1 != 4 Someone wants me (1) in numeric context Someone wants me (3) in numeric context 3 == 1 3 == 3 3 != 4 Someone wants me (1) in numeric context Someone wants me (4) in numeric context 4 == 1 4 != 3 4 == 4
Apparently, it works by also using fallback => 1 in this case, but it won't work in my case, since my complicated class won't let Perl default comparison operators work.

By the way, this is perl, v5.8.7 built for i486-linux-gnu-thread-multi.

So, my question is, why Perl wants to force the variables (which come from a tied array) into numeric context, before even trying to apply my overloaded operator? And why does it do that only in the first iteration of the inner loop?

I realized that the BUGS section of the overload man page says something about the relation of tie and overlaod, but I simply can not grok the wording. Is this the bug I have been running into? How to fix it?

Replies are listed 'Best First'.
Re: Weird interaction of tie and overload
by ikegami (Patriarch) on Jul 26, 2005 at 16:22 UTC

    If I add

    use overload '0+' => \# sub num { print "[$_[0]->[0]]"; return $_[0]->[0]; }

    I get:

    [1][1]1 == 1 1 != 3 1 != 4 [1][3]3 != 1 3 == 3 3 != 4 [1][4]4 != 1 4 != 3 4 == 4

    In other words, it fails on each first pass of the inner loop. (In might also be failing on the first pass of the outer loop, but we can't tell.) I don't know what that means, though.

      In other words, it fails on each first pass of the inner loop. (In might also be failing on the first pass of the outer loop, but we can't tell.) I don't know what that means, though.
      Dear ikegami! If you don't know the answer, how should I? Where should I go from here? Should I post this to p5p? Might this be a bug?
        Ha! Yeah, this has to be a bug. I don't know if it's related to overload's known bug or not. I have no idea what you should do. I don't know anything about p5p other than they exist.