2012-11-11 4 views
8

Mit anderen Worten, wie kann ich für Coderef "Gleichheit" überprüfen?Wie kann ich überprüfen, ob ein Perl-Skalar einen Verweis auf eine bestimmte Subroutine enthält?

Das Smartmatch Operator funktioniert nicht for obvious reasons (würde es als CODE->(ANY) behandeln), aber ich habe es in dem Beispiel enthalten zu zeigen, was mich nach:

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" ; 

Antwort

11

Sie normal verwenden können (numeric) Gleichheit (==), wie es der Fall mit allen Referenzen ist:

Perl> $selected == \&foo 


Perl> $selected == \&bar 


Perl> $selected == \&baz 
1 

Live in action here

dass bricht, wenn t Der Verweis ist gesegnet mit etwas, das == oder 0+ überlädt (was für Coderefs unwahrscheinlich ist). In diesem Fall würden Sie Scalar::Util::refaddr($selected) vergleichen.

Von man perlref:

Referenz verwendet werden, wie eine Anzahl eine ganze Zahl erzeugt seine Speicherstelle im Speicher darstellt. Die einzige nützliche Sache, die damit zu tun ist, ist, zwei Referenzen numerisch zu vergleichen, um zu sehen, ob sie sich auf den gleichen Ort beziehen.

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

Ich bin überrascht, dass das funktioniert. Möchten Sie das erklären? – Zaid

+0

@Zaid siehe bearbeiten. – jpalecek

+0

Beachten Sie, dass dadurch sogar zwischen mehreren Instanzen desselben Closures unterschieden wird, obwohl derselbe zugrunde liegende Code aufgerufen wird: 'for my $ a (1..2) {push @x, sub {print $ a}} $ x 0](); $ x [1](); drucken $ x [0]! = $ x [1] '' – ysth

Verwandte Themen