Какой самый элегантный способ в Perl развернуть итератор в список? - PullRequest
6 голосов
/ 10 октября 2010

У меня есть итератор с этим интерфейсом: $ hit-> next_hsp

Текущая реализация для его просмотра:

my @list;
while ( my $hsp = $hit->next_hsp ) {
    push( @list, $hsp );
}

Теперь я думаю, что могут быть лучшие способысделать это в меньшем количестве кода.Что скажешь, укладчики?

Ответы [ 3 ]

5 голосов
/ 10 октября 2010

Все итераторы, которые я когда-либо видел, возвращают undef, чтобы показать, что они исчерпаны. Поэтому вы должны написать while (defined(my $hsp = $hit->next_hsp)). В следующем примере демонстрируется ошибка в вопросе, которая проверяет правдивость (прерывается на 1) вместо определенности (проходит «отрыв»).

use 5.010;
my $hit = __PACKAGE__;

sub next_hsp {
    state $i;
    $i++;
    return ['mumble', 4, 3, 2, 1, 0, 'liftoff']->[$i];
}

# insert snippet from question here
3 голосов
/ 11 октября 2010

Не беспокойтесь об игре в гольф, код у вас выглядит просто отлично (кроме других ответов об использовании defined).Однако, если вы обнаружите, что повторяете этот паттерн, на ум приходят 2 вещи.

Первое очевидно, преобразовайте его в служебную функцию, чтобы у вас было my @list = expand($hit).

Второй вопроснемного глубже - но для меня пахнет больше, чем игра в гольф.Весь смысл итераторов в том, чтобы потреблять их по мере необходимости, поэтому, если вы обнаружите, что делаете это часто, вы уверены, что это действительно правильно?Возможно, вы перемещаете эти данные за пределы своего собственного API, поэтому вы ограничены в выборе других, но если у вас есть возможность использовать итератор, а не список, возможно, это будет более чистое решение.

3 голосов
/ 10 октября 2010

Это полностью зависит от реализации итератора.Если next_hsp является единственным доступным методом, значит, вы делаете это правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...