List Info

Thread: Scalar::Util::refaddr




Scalar::Util::refaddr
user name
2007-10-08 06:02:05
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
    }
-- 
Met vriendelijke groet,  Kind regards,  Korajn salutojn,

  Juerd Waalboer:  Perl hacker  <#####juerd.nl>  <http://juerd.nl/sig>
  Convolution:     ICT solutions and consultancy
<salesconvolution.nl>

Re: Scalar::Util::refaddr
user name
2007-10-08 06:16:22
Juerd Waalboer writes:
> Does anyone know why it wasn't done in this much
simpler way?
> 
>     sub refaddr($) {
>         ref($_[0]) ? 0+$_[0] : undef
>     }

Overloading.

  $ cat o.pl
  use strict;
  {
      package C;
      use overload '+' => sub ;
      sub new { bless {}, $_[0] }
  }
  sub refaddr($) {
      ref($_[0]) ? 0+$_[0] : undef
  }
  my $x = C->new;
  my $y = C->new;
  print refaddr $x;
  print refaddr $y;
  $ perl -wl o.pl
  17
  17

-- 
Aaron Crane

Re: Scalar::Util::refaddr
user name
2007-10-08 06:20:33
On 10/8/07, Juerd Waalboer <juerdconvolution.nl> 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. 

Yves

-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

Re: Scalar::Util::refaddr
user name
2007-10-08 06:20:59
On Mon, Oct 08, 2007 at 12:16:22PM +0100, Aaron Crane
wrote:
> Juerd Waalboer writes:
> > Does anyone know why it wasn't done in this much
simpler way?
> > 
> >     sub refaddr($) {
> >         ref($_[0]) ? 0+$_[0] : undef
> >     }
> 
> Overloading.

However, reblessing and numification is just as effective
as
reblessing and stringification, but simpiler.

On the other hand, this is a silly discussion about
microoptimization
of a fallback.

   -=- James Mastros

Re: Scalar::Util::refaddr
user name
2007-10-08 06:44:54
On Oct 8, 2007, at 6:20 AM, James Mastros wrote:
> On Mon, Oct 08, 2007 at 12:16:22PM +0100, Aaron Crane
wrote:
>> Juerd Waalboer writes:
>>> Does anyone know why it wasn't done in this
much simpler way?

It was at one point, but it did not work on some 64bit
platforms  
because you need the result to be unsigned.

>>>
>>>     sub refaddr($) {
>>>         ref($_[0]) ? 0+$_[0] : undef
>>>     }
>>
>> Overloading.
>
> However, reblessing and numification is just as
effective as
> reblessing and stringification, but simpiler.
>
> On the other hand, this is a silly discussion about
microoptimization
> of a fallback.

Right. On most systems today this code is not used because
the XS  
code is compiled when perl is installed.

Graham.


Re: Scalar::Util::refaddr
user name
2007-10-08 06:52:45
At 1:23 PM +0200 10/8/07, demerphq wrote:
>On 10/8/07, Juerd Waalboer <juerdconvolution.nl> 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?



Liz

Re: Scalar::Util::refaddr
country flaguser name
United States
2007-10-08 08:26:36
On Oct 8, 7:44 am, gb...pobox.com (Graham Barr)
wrote:
> On Oct 8, 2007, at 6:20 AM, James Mastros wrote:
>
> > On Mon, Oct 08, 2007 at 12:16:22PM +0100, Aaron
Crane wrote:
> >> Juerd Waalboer writes:
> >>> Does anyone know why it wasn't done in
this much simpler way?
>
> It was at one point, but it did not work on some 64bit
platforms  
> because you need the result to be unsigned.
>
>
>
> >>>     sub refaddr($) {
> >>>         ref($_[0]) ? 0+$_[0] : undef
> >>>     }
>
> >> Overloading.
>
> > However, reblessing and numification is just as
effective as
> > reblessing and stringification, but simpiler.
>
> > On the other hand, this is a silly discussion
about microoptimization
> > of a fallback.
>
> Right. On most systems today this code is not used
because the XS  
> code is compiled when perl is installed.
>
> Graham.

Two reasons I'd hope my question might be seen as rising
slightly
above the silly:

1.)  Your code, Graham, is generally held out as an example
of how to
do things, so you have readers as well as users.  Which is
why I asked
about it.  I see a lot of code I don't understand on CPAN,
and don't
bother asking about that, because given the general standard
of CPAN
code doing so would be, well, silly.

2.) From time to time you do want to optimize Perl code, and
it's
usually wise to optimize for the worst case, not the best or
even the
average.

I am unsurprised to discover that the code is the way it is
for good
reasons, and that my perplexity at it was a product of my
ignorance.
If my question stimulates its further improvement, the
result will
have be entirely unsilly.

jeffrey kegler


Re: Scalar::Util::refaddr
user name
2007-10-08 09:53:28
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 <juerdconvolution.nl> 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
Re: Scalar::Util::refaddr
user name
2007-10-09 04:56:42
> sub refaddr {
>     if ( overload::Method( $_[0], '0+' ) ) {
>         rebless ...;
>         my $refaddr = 0+$_[0];
>         rebless ...;
>         return $refaddr;
>     }
>     else {
>         return 0+$_[0];
>     }
> }


This will fail if the object has overloaded stringification,
but no
numification overload:

    #!/usr/bin/perl

    use strict;
    use warnings;
    no warnings 'syntax';
    
    use overload '""' => &stringify,
    ;
        
    sub refaddr ($) {
        if ( overload::Method( $_[0], '0+' ) ) {
            my $pkg = ref $_ [0];
            bless $_ [0], 'Scalar::Util::Fake';
            my $refaddr = 0+$_[0];
            bless $_ [0], $pkg;
            return $refaddr;
        }
        else {
            return 0+$_[0];
        }
    }

    sub stringify {return 17};

    my $foo = bless [] => 'main';
    print refaddr $foo, "n";

    __END__
    Operation "+": no method found,
            left argument has no overloaded magic,
            right argument in overloaded package main at
/tmp/foo line 19.


But you also may have '+' overloading. Or 'fallback' may
have been set.
And there may be 'nomethod' overloading.



Abigail
Re: Scalar::Util::refaddr
user name
2007-10-10 04:59:06
* Juerd Waalboer <juerdconvolution.nl>
[2007-10-08 13:11]:
> 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;
> }

FWIW, having established that there’s no better way to
write that
function, I really dislike the way that spreads the
reblessing
logic around the function based on a flag. Is there any
reason
not to write it this way?

    sub refaddr($) {
      my $pkg = ref($_[0]) or return undef;

      my $addr;
      if (blessed($_[0])) {
        $addr .= bless $_[0], 'Scalar::Util::Fake';
        bless $_[0], $pkg;
      }
      else {
        $addr .= $_[0];
      }

      $addr =~ /0x(w+)/;
      local $^W;
      hex $1;
    }

It’s a minor thing, I know, but I do think it makes the
code
better.

-- 
*AUTOLOAD=*_;sub
_{s/(.*)::(.*)/print$2,(",$/","
")[defined wantarray]/e;$1}
&Just->another->Perl->hack;
#Aristotle

[1-10] [11-18]

about | contact  Other archives ( Real Estate discussion Medical topics )