Comparing a reference?

Discussion in 'Perl Misc' started by Tim McDaniel, Jan 30, 2013.

  1. Tim McDaniel

    Tim McDaniel Guest

    I inherited code that had, in effect,

    my $kind = 'Val';
    ...
    if ($kind eq 'Val')

    For various reasons, I want to change it to

    my $kind = \&some_sub;

    Is there a reliable, guaranteed way to do that and still have the
    conditional? (This is in 5.8.8 and I have no way to change that.)

    man perlref says

    Using a string or number as a reference produces a symbolic
    reference, as explained above. Using a reference as a number
    produces an integer representing its storage location in memory.
    The only useful thing to be done with this is to compare two
    references numerically to see whether they refer to the same
    location.

    if ($ref1 == $ref2) { # cheap numeric compare of references
    print "refs 1 and 2 refer to the same thing\n";
    }

    I also ran across
    http://stackoverflow.com/questions/4064001/how-should-i-compare-perl-references
    , where there was one reply that said

    The function you are looking for is refaddr from Scalar::Util
    (after ensuring that the values being compared really are
    references):

    use Scalar::Util 'refaddr';

    if ($obj1 and ref($obj1) and $obj2 and ref($obj2) and
    refaddr($obj1) == refaddr($obj2))
    {
    # objects are the same...
    }

    with tchrist replying "The extraordinary measures taken by
    cpan/List-Util/lib/Scalar/Util/PP.pm's refaddr() function to divine
    the referent's real address are exceeded only by the blessed()
    function's measures to find the package name.", and a reply to that
    that it's in the Perl core and compiled, so it's cheap.

    Is there a reason to use SCalar::Util::refaddr instead of ==?

    --
    Tim McDaniel,
    Tim McDaniel, Jan 30, 2013
    #1
    1. Advertising

  2. Tim McDaniel

    Tim McDaniel Guest

    In article <>,
    Ben Morrow <> wrote:
    >
    >Quoth :
    >> Is there a reason to use SCalar::Util::refaddr instead of ==?

    >
    >The only reason is if there is a chance either ref might point to an
    >object which overloads either == or numify, or if there is a chance
    >$kind might not hold a ref at all. If you know you are dealing with
    >unblessed refs there is no reason not to use ==.
    >
    >If there is a chance you might be running under ithreads, it's important
    >to check against the current value of \&some_sub, rather than trying to
    >cache the numeric value, since the value of the ref will change when a
    >new thread is forked.


    Thank you for the quick response.

    $kind is one reference out of four possible refs, along the lines of

    my $lookup = {
    CASE1 => \&Pkg::Sub1,
    CASE2 => \&Pkg::Sub2,
    CASE3 => \&Pkg::Sub3,
    CASE4 => \&Pkg::Sub4,
    };
    $kind = $lookup->{$arg};
    return unless $kind;

    There is no threading, no blessing, and no object munging in the 40
    lines between setting and this comparison.

    Reading in further Google hits, though, I think I may do refaddr just
    to be paranoid.

    --
    Tim McDaniel,
    Tim McDaniel, Jan 30, 2013
    #2
    1. Advertising

  3. Tim McDaniel

    Tim McDaniel Guest

    In article <keca6v$d31$>,
    Tim McDaniel <> wrote:
    >$kind is one reference out of four possible refs, along the lines of
    >
    > my $lookup = {
    > CASE1 => \&Pkg::Sub1,
    > CASE2 => \&Pkg::Sub2,
    > CASE3 => \&Pkg::Sub3,
    > CASE4 => \&Pkg::Sub4,
    > };
    > $kind = $lookup->{$arg};
    > return unless $kind;
    >
    >There is no threading, no blessing, and no object munging in the 40
    >lines between setting and this comparison.
    >
    >Reading in further Google hits, though, I think I may do refaddr just
    >to be paranoid.


    I just realized that $arg is also in scope at the point of the
    comparison. So instead of doing

    if (Scalar::Util::refaddr($kind) == Scalar::Util::refaddr(\&Pkg::Sub1)) {

    I can simply do

    if ($arg eq 'CASE1') {

    and finesse away the whole issue.

    Still, thank you for the answer.

    --
    Tim McDaniel,
    Tim McDaniel, Jan 31, 2013
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Darren
    Replies:
    0
    Views:
    484
    Darren
    Oct 11, 2004
  2. Dude
    Replies:
    0
    Views:
    343
  3. ce
    Replies:
    1
    Views:
    2,963
  4. sam pal
    Replies:
    3
    Views:
    527
    E. Robert Tisdale
    Jul 16, 2003
  5. Craig Nicol
    Replies:
    2
    Views:
    455
    Craig Nicol
    May 10, 2004
Loading...

Share This Page