Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

A Scalar::Util::refaddr Oddity

by Zaxo (Archbishop)
on Sep 25, 2005 at 15:40 UTC ( [id://494914]=perlquestion: print w/replies, xml ) Need Help??

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

During a hot cb discussion of Scalar::Util::refaddr, I noticed that the pure perl version of the function will alter an unblessed reference passed to it. The sub goes as follows:

sub refaddr($) { my $pkg = ref($_[0]) or return undef; bless $_[0], 'Scalar::Util::Fake'; "$_[0]" =~ /0x(\w+)/; my $i = do { local $^W; hex $1 }; bless $_[0], $pkg; $i; }
The reblessing to a fake namespace is to eliminate problems from overloading in the target's class, the issue that first made me look at the source.

The oddity is that an unblessed reference will wind up blessed if it is the argument of refaddr. Here's a demo:

use DynaLoader; # disable XS loading sub DynaLoader::bootstrap {1} # thanks, demerphq use Scalar::Util qw(refaddr); my $foo = {}; print $foo, $/; refaddr $foo; print $foo, $/; __END__ HASH(0x804b3f8) HASH=HASH(0x804b3f8)
The normally-loaded XS version of the function does not exhibit that behavior.

Pure perl refaddr can be fixed to act like the XS version by making the bless lines conditional on a stored value of Scalar::Util::blessed($_[0]).

My question: Is it worth fixing? Are there any odd side effects of that blessing? Are any significant properties changed?

After Compline,
Zaxo

Replies are listed 'Best First'.
Re: A Scalar::Util::refaddr Oddity
by ambrus (Abbot) on Sep 25, 2005 at 20:24 UTC
    Are there any odd side effects of that blessing?

    I think yes.

    Firstly, if someone uses the string value of an unblessed reference as a hash key (for example for memoizing some function of the reference), then calling refaddr on this reference would change the string and thus make the program fail. That's a bad practice anyway, as string values of scalar references can change even without reblessing, as the prefix can be SCALAR, REF, GLOB etc. You should use the numeric values of references instead. However, some code can still use it, do I'd consider this an odd side effect.

    Secondly, doesn't this function blow up on a reference to a constant, such as $x = \5; $ad = refaddr($x);? It still makes sense to take the address of such a reference.

      On blowup, it sure does, with "Modification of constant" error. Thanks, I hadn't noticed that one.

      After Compline,
      Zaxo

Re: A Scalar::Util::refaddr Oddity
by nothingmuch (Priest) on Sep 25, 2005 at 16:52 UTC
    I think it's worth fixing even if just to make sure accidental users don't get surprised.

    Most people don't expect to use the pure perl Scalar::Util, so if by accident they do, they should get completely equivalent behavior (even if it's 100% compatible it might not be equivalent), so appearance also matters, IMHO.

    -nuffin
    zz zZ Z Z #!perl

      I agree that the behaviors should be identical, though I don't understand why the pure-perl version uses that code versus the 0 + $object idiom.

      use strict; use warnings; use Scalar::Util qw( refaddr ); sub refaddr_pp { return if not ref $_[0]; return 0 + $_[0]; } my $obj = bless {}, 'Foo'; my $ref = {}; print 'refaddr $obj: ', refaddr($obj), "\n"; print 'refaddr_pp $obj: ', refaddr_pp($obj), "\n\n"; print 'refaddr $ref: ', refaddr($ref), "\n"; print 'refaddr_pp $ref: ', refaddr_pp($ref), "\n";

      Prints

      refaddr $obj: 149445664 refaddr_pp $obj: 149445664 refaddr $ref: 149445904 refaddr $ref: 149445904

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

        I don't understand why the pure-perl version uses that code versus the 0 + $object idiom.

        Because that idiom fails if $object overloads addition to do something else.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://494914]
Approved by ww
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-04-19 06:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found