2012-11-11 19 views
8

In altre parole, come posso verificare la presenza di "uguaglianza" di coder?Come posso verificare se uno scalare Perl contiene un riferimento ad una determinata subroutine?

L'operatore SmartMatch non funziona for obvious reasons (sarebbe trattarlo come CODE->(ANY)), ma ho incluso nel esempio per mostrare quello che sto cercando:

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

risposta

11

È possibile utilizzare normale (numerico) l'uguaglianza (==), come è il caso con tutti i riferimenti:

Perl> $selected == \&foo 


Perl> $selected == \&bar 


Perl> $selected == \&baz 
1 

Live in action here

che si rompe quando t Il riferimento è benedetto da qualcosa che sovraccarica lo == o 0+ (che è improbabile per i codec). In tal caso, confrontare Scalar::Util::refaddr($selected).

Da man perlref:

Usare un riferimento come numero produce un intero che rappresenta la sua posizione di memorizzazione nella memoria. L'unica cosa utile da fare con questo è confrontare numericamente due riferimenti per vedere se si riferiscono alla stessa posizione.

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

Sono sorpreso che questo funziona. Cura di spiegare? – Zaid

+0

@Zaid vedi modifica. – jpalecek

+0

Si noti che questo si distinguerà anche tra più istanze della stessa chiusura, anche se lo stesso codice sottostante è chiamato: 'per il mio $ a (1..2) {push @x, sub {print $ a}} $ x [ 0](); $ x [1](); stampa $ x [0]! = $ x [1] '' – ysth

Problemi correlati