Использование карты или grep в Perl

Я пишу perl-код полный рабочий день в течение пары месяцев (биоинформатика), и я всегда стараюсь улучшить свои навыки. Только сегодня мне стало ясно, что я никогда не использую карту или grep. Оглядываясь назад на мой код, я понимаю, что эти инструменты могли бы сэкономить мне пару строк здесь или там, но только за счет гибкости цикла foreach. Мой вопрос следующий:

Существуют ли какие-либо обстоятельства, с которыми вы столкнулись, когда использование карты или grep принесло значительное преимущество перед циклом foreach/for, помимо сохранения строки или двух из кода?

Спасибо за ваше время!

Ответы

Ответ 1

Schwartzian Transform будет примером:

@sorted = map  { $_->[0] }
          sort { $a->[1] cmp $b->[1] }
          map  { [$_, foo($_)] }
          @unsorted;

Вы можете сделать это с помощью кучи контуров foreach, но вам придется выбирать их отдельно, чтобы выяснить, что происходит; как только вы увидите Шварццианское Преобразование, вы сразу узнаете идиому.

В целом я думаю, что map и grep хороши тем, что они позволяют четко и компактно представлять ваши намерения без слоев синтаксиса. Если вы видите map, тогда вы знаете, что происходит какое-то простое преобразование структуры данных; если вы видите grep, тогда вы знаете, что происходит некоторая фильтрация/выбор. Вы можете сделать все это с помощью foreach, но цель вашего кода не такая ясная, как это было бы с map или grep; вы могли бы даже сделать все это с помощью if и goto, если бы захотели, но тогда ваши намерения были бы захоронены под еще большим синтаксисом и отслеживанием состояния.

Ответ 2

Я постоянно использую map и grep. И apply, first, any и многие другие из List::MoreUtils. Я нахожу, что, в общем, они объясняют, что делает код, в отличие от того, как это делает код.

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

Например, если моя спецификация говорит, что я буду делать foo(), если $blah находится в некотором списке, мой код читается именно так:

foo() if any { $_ eq $blah } some_list();

Такая же идея для остальных этих инструментов. Код и спецификация выглядят устрашающе похожими, и что одна из замечательных вещей о Perl.