Я пытаюсь записать некоторый псевдокод для поиска списка подобных объектов для первого, атрибуты которого соответствуют определенным значениям. Чтобы сделать это, я должен назвать набор методов доступа и проверить все их значения один за другим. Я хотел бы использовать абстракцию как это:
sub verify_attribute {
my ($object, $attribute_method, $wanted_value) = @_;
if ( call_method($object, $attribute_method) ~~ $wanted_value ) {
return 1;
}
else {
return;
}
}
Затем я могу циклично выполниться через хеш, ключи которого являются именами метода доступа и чьи значения являются значениями, которые я ищу для тех атрибутов. Например, если тот хеш называют %wanted
, Я мог бы использовать код как это для нахождения объекта, который я хочу:
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;
}
Конечно, единственная проблема - это call_method
не экс-находится. Или он? Как я могу назвать метод, если у меня есть строка, содержащая ее имя? Или есть ли лучшее решение этой целой проблемы?
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;
}
Да, вы можете вызывать методы таким образом. Никакая строка (или любой другой) eval не задействована.
Кроме того, замените ==
на eq
или = ~
в зависимости от типа данных ...
Или, для дополнительных кредитов, сделайте это функциональным способом: (all () действительно должен быть частью List :: Util!)
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;
Обновление: по общему признанию, первое решение является менее запутанным, поэтому предпочтительнее . Но, отвечая на вопросы, вы добавили немного сахара, чтобы вам было интересно! ; -)