2012-11-11 23 views
8

Nói cách khác, làm thế nào tôi có thể kiểm tra coderef "bình đẳng"?Làm cách nào để kiểm tra xem liệu một vô hướng Perl có tham chiếu đến một chương trình con nhất định không?

Nhà điều hành smartmatch không hoạt động for obvious reasons (sẽ đối xử với nó như CODE->(ANY)), nhưng tôi đã bao gồm nó trong ví dụ này để hiển thị những gì tôi sau:

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

Trả lời

11

Bạn có thể sử dụng bình thường (số) bình đẳng (==), như là trường hợp với tất cả các tài liệu tham khảo:

Perl> $selected == \&foo 


Perl> $selected == \&bar 


Perl> $selected == \&baz 
1 

Live in action here

Đó phá vỡ khi t ông tham khảo được may mắn với một cái gì đó mà quá tải == hoặc 0+ (đó là không cho coderefs). Trong trường hợp đó, bạn sẽ so sánh Scalar::Util::refaddr($selected).

Từ man perlref:

Sử dụng một tài liệu tham khảo như một số sản xuất một số nguyên đại diện cho vị trí lưu trữ của nó trong bộ nhớ. Điều hữu ích duy nhất được thực hiện với điều này là so sánh hai tham chiếu bằng số để xem liệu chúng có tham chiếu đến cùng một vị trí hay không.

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

Tôi rất ngạc nhiên khi công trình này hoạt động. Quan tâm để giải thích? – Zaid

+0

@Zaid xem chỉnh sửa. – jpalecek

+0

Lưu ý rằng điều này sẽ phân biệt ngay cả giữa nhiều phiên bản của cùng một đóng, mặc dù cùng một mã cơ bản được gọi là: 'cho $ a (1..2) {push @x, sub {print $ a}} $ x [ 0](); $ x [1](); in $ x [0]! = $ x [1] '' – ysth

Các vấn đề liên quan