2012-11-11 9 views
8

Innymi słowy, w jaki sposób mogę sprawdzić koderef "równość"?Jak mogę sprawdzić, czy skalar Perla zawiera odniesienie do określonego podprogramu?

Operator smartmatch nie działa for obvious reasons (by traktować go jako CODE->(ANY)), ale podaję go w przykładzie pokazać, co jestem po:

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

Odpowiedz

11

Można użyć normalny (numeryczna) równość (==), jak ma to miejsce w przypadku wszelkich odniesień:

Perl> $selected == \&foo 


Perl> $selected == \&bar 


Perl> $selected == \&baz 
1 

Live in action here

to łamie gdy T odniesienie jest pobłogosławione czymś, co przeciąży == lub 0+ (co jest mało prawdopodobne w przypadku coderefów). W takim przypadku możesz porównać Scalar::Util::refaddr($selected).

Od man perlref:

Korzystanie odniesienie jak wiele daje liczbę całkowitą reprezentującą jego lokalizację zapisu w pamięci. Jedyną przydatną rzeczą do zrobienia jest porównanie dwóch wartości liczbowych w celu sprawdzenia, czy odnoszą się one do tej samej lokalizacji.

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

Jestem zaskoczony, że to działa. Chcesz wyjaśnić? – Zaid

+0

@Zaid patrz edycja. – jpalecek

+0

Należy zauważyć, że rozróżni to nawet między wieloma wystąpieniami tego samego zamknięcia, mimo że wywoływany jest ten sam podstawowy kod: 'dla mojego $ a (1..2) {push @x, sub {print $ a}} $ x [ 0](); $ x [1](); print $ x [0]! = $ x [1] '' – ysth

Powiązane problemy