Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if a Perl scalar holds a reference to a certain subroutine?

Tags:

perl

In other words, how can I check for coderef "equality"?

The smartmatch operator doesn't work for obvious reasons (would treat it as CODE->(ANY)), but I've included it in the example to show what I'm after:

use strict;
use warnings;
use feature 'say';

sub pick_at_random {

    my %table = @_;
    return ( values %table )[ rand( keys %table ) ];
}

my %lookup = ( A => \&foo,
               B => \&bar,
               C => \&baz );

my $selected = pick_at_random( %lookup );

say $selected ~~ \&foo ? "Got 'foo'" :
    $selected ~~ \&bar ? "Got 'bar'" :
    $selected ~~ \&baz ? "Got 'baz'" :
                         "Got nadda" ;
like image 577
Zaid Avatar asked Nov 11 '12 16:11

Zaid


People also ask

What does @_ mean in Perl?

Using the Parameter Array (@_) Perl lets you pass any number of parameters to a function. The function decides which parameters to use and in what order.

What does REF do in Perl?

ref - Perldoc Browser. Examines the value of EXPR, expecting it to be a reference, and returns a string giving information about the reference and the type of referent. If EXPR is not specified, $_ will be used. If the operand is not a reference, then the empty string will be returned.


1 Answers

You can use normal (numeric) equality (==), as is the case with all references:

Perl> $selected == \&foo


Perl> $selected == \&bar


Perl> $selected == \&baz
1

Live in action here

That breaks when the reference is blessed with something that overloads == or 0+ (which is unlikely for coderefs). In that case, you'd compare Scalar::Util::refaddr($selected).

From man perlref:

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";
       }
like image 136
jpalecek Avatar answered Oct 08 '22 17:10

jpalecek