Re: Scalar::Util::refaddr On Mon, Oct 08, 2007 at 01:52:45PM +0200, Elizabeth Mattijsen wrote:
} At 1:23 PM +0200 10/8/07, demerphq wrote:
} >On 10/8/07, Juerd Waalboer  wrote:
} >> Seen on Perl Monks:
} >> | I do wonder why in the refaddr code in non-XS Scalar::Util, the code
} >> | stringifies the reference then pulls a number out with a regex. As far
} >> | as I can tell in terms of complexity and time-efficiency, that's 
} >> clearly
} >> | inferior to forcing the reference to numeric.
} >> -- Jeffrey Kegler at http://perlmonks.org/?node_id=643288
} >>
} >> The snippet in question is:
} >>
} >>     sub refaddr($) {
} >>       my $pkg = ref($_[0]) or return undef;
} >>       if (blessed($_[0])) {
} >>         bless $_[0], 'Scalar::Util::Fake';
} >>       }
} >>       else {
} >>         $pkg = undef;
} >>       }
} >>       "$_[0]" =~ /0x(\\w+)/;
} >>       my $i = do { local $^W; hex $1 };
} >>       bless $_[0], $pkg if defined $pkg;
} >>       $i;
} >>     }
} >>
} >> This does indeed seem a bit inefficient, especially with the 
} >>double reblessing
} >> going on that's probably only there to work around issues caused by the
} >> stringification.
} >>
} >> Does anyone know why it wasn't done in this much simpler way?
} >>
} >>     sub refaddr($) {
} >>         ref($_[0]) ? 0+$_[0] : undef
} >>     }
} >
} >Because of overloaded numification it cant be written that way. If I
} >overload nummification I can make that return 42 everytime. :-)
} >
} >However given that they are doing the rebless logic i dont see why the
} >regex part is required.
} >
} >     sub refaddr($) {
} >       my $pkg = ref($_[0]) or return undef;
} >       if (blessed($_[0])) {
} >         bless $_[0], 'Scalar::Util::Fake';
} >       }
} >       else {
} >         $pkg = undef;
} >       }
} >       my $i = 0+$_[0];
} >       bless $_[0], $pkg if defined $pkg;
} >       $i;
} >     }
} >
} >Alternatively the entire rebless logic could be chucked and replaced
} >with a call to overload::StrVal() which i think has been around as
} >long as overload has,then the regex part could stay. I could have
} >sworn there was a numeric equivelent to overload::StrVal(), but i cant
} >find it documented, which suggests that if it does exist it hasnt
} >always, which is why the code doesnt use that.
} >
} >I guess however the objective could have been to avoid using overload
} >at all. Alternatively it could be a speed issue. overload::StrVal() is
} >pretty slow as far as I recall.
} >
} >Core code that looks this crufty is usually that way for a reason. ;-)
} 
} Now if there was an easy and efficient way to find out whether 
} numification is *not* overloaded on an object, you wouldn't have to 
} go through the whole rigamerole of reblessing, but simply return 0 + 
} $_[0], no?
} 
} Is there an easy and efficient way to check this?

sub refaddr {
    if ( overload::Method( $_[0], '0+' ) ) {
        rebless ...;
        my $refaddr = 0+$_[0];
        rebless ...;
        return $refaddr;
    }
    else {
        return 0+$_[0];
    }
}

-- 
Josh
