2010-04-27 18 views
6

Öznitelikleri belirli değerlerle eşleşen ilk nesneye ait benzer nesneler arasında arama yapmak için soyut bir kod yazmaya çalışıyorum. Bunu yapabilmek için, bir grup erişimci yöntemini çağırmalı ve tüm değerlerini tek tek kontrol etmeliyim. Böyle bir soyutlama kullanmak istiyorum:Perl'de, bir dizede sahip olduğum bir yöntemi nasıl arayabilirim?

sub verify_attribute { 
    my ($object, $attribute_method, $wanted_value) = @_; 
    if (call_method($object, $attribute_method) ~~ $wanted_value) { 
     return 1; 
    } 
    else { 
     return; 
    } 
} 

Sonra can tuşları erişimci yöntem isimleri ve değerleri ben bu özelliklerin arıyorum değerlerdir bir karma döngü. gelen esrar %wanted denir Örneğin, ben istediğiniz nesneyi bulmak için böyle bir kod kullanabilirsiniz:

Tabii
my $found_object; 
FINDOBJ: foreach my $obj (@list_of_objects) { 
    foreach my $accessor (keys %wanted) { 
     next FINDOBJ unless verify_attribute($obj, $accessor, $wanted{$accessor}); 
    } 
    # All attrs verified 
    $found_object = $obj; 
    last FINDOBJ; 
} 

, tek sorun call_method exsit olmamasıdır. Yoksa öyle mi? Adını içeren bir dizem varsa nasıl bir yöntem arayabilirim? Yoksa bu sorunun tamamı için daha iyi bir çözüm var mı?

cevap

5
my $found_object; 
FINDOBJ: foreach my $obj (@list_of_objects) { 
    foreach my $accessor (keys %wanted) { 
    next FINDOBJ unless $obj->$accessor() == $wanted{$accessor}; 
    } 
    # All attrs verified 
    $found_object = $obj; 
    last; 
} 

Evet, yöntemleri bu şekilde çağırabilirsiniz. Hiçbir dize (veya başka herhangi bir) değerlendirmeye dahil. Ayrıca ... eq veya =~ verilerin türüne bağlı olarak

== yerine Veya, bazı ekstra krediler için, bunu fonksiyonel şekilde yapın: (hepsi() gerçekten List :: Util bir parçası olmalıdır!)

use List::Util 'first'; 

sub all (&@) { 
    my $code = shift; 
    $code->($_) || return 0 for @_; 
    return 1; 
} 

my $match = first { 
        my $obj = $_; 
        all { $obj->$_ == $attrs{$_} } 
         keys %wanted 
        } @list_of_objects; 

Güncelleme: Kuşkusuz, ilk çözüm daha az Karartılmış biridir, bu nedenle tercih edilir. Ama birileri soruları yanıtlarken, kendiniz için de ilginç hale getirmek için biraz şeker eklediniz! ;-)

+0

Ye ah, birkaç sanık önce bunu deneme yanılma ile çözdüm. Güzel. –

+1

Sadece 'List :: AllUtils' kullanıyorum. Veya Util :: Any qw (: all) '. Ama örnek kodumda çekirdeğe yapışmaya çalışıyorum. –

+0

Bunun işe yaraması için, sıkı kontrolleri “katı değil” (mutlaka küresel olarak değil) ile devre dışı bırakmanız gerektiğine inanıyorum - doğru mu? –

0

Fonksiyonel yolu serin, ama benim gibi Aptallar eval kurallar için:

test.pl

#!/usr/bin/perl -l 
use F; 
my $f = F->new(); 

my $fun = 'lol'; # method of F 

eval '$f->'.$fun.'() '; # call method of F, which name is in $fun var 

F.pm

package F; 

sub new 
{ 
    bless {}; 
} 


sub lol 
{ 
    print "LoL"; 
} 
1; 

[root @ ALT-24 kök] # perl test.pl

LoL

İlgili konular