2012-11-11 5 views
8

즉, coderef "평등"을 어떻게 확인할 수 있습니까?Perl 스칼라가 특정 서브 루틴에 대한 참조를 보유하고 있는지 어떻게 확인할 수 있습니까?

smartmatch 연산자 (CODE->(ANY)로 취급 것) for obvious reasons 작동하지 않습니다,하지만 난 후 난 무엇을 보여주기 위해 예제를 포함 시켰습니다 :

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

답변

11

당신은 숫자 (보통 사용할 수 있습니다) 평등 (==), 모든 참조의 경우처럼이 :

Perl> $selected == \&foo 


Perl> $selected == \&bar 


Perl> $selected == \&baz 
1 

Live in action here

그 때 t을 나누기 그는 참조 번호가 == 또는 0+ (이는 코드 작성자에게는 없을 것입니다)에 과부하가 걸린 것에 축복받습니다. 이 경우 Scalar::Util::refaddr($selected)을 비교해보십시오. 개수가 메모리에서의 저장 위치를 ​​나타내는 정수로 생성 참조하여

: man perlref 가입일

. 이 작업을 수행하는 유일한 방법은 두 개의 참조를 숫자로 비교하여 동일한 위치를 참조하는지 확인하는 것입니다.

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

놀랍습니다. 설명해 주겠다고? – Zaid

+0

@Zaid 편집을 참조하십시오. – jpalecek

+0

같은 기본 코드가 호출 되더라도 동일한 클로저의 여러 인스턴스 사이에서도 구별 할 수 있습니다. 'for my $ a (1..2) {push @x, sub {print $ a}} $ x [ 0](); $ x [1](); print $ x [0]! = $ x [1] '' – ysth