Краткое выражение foreach в одну строку - PullRequest
6 голосов
/ 20 февраля 2009

В Perl часто можно избежать использования блоков управления, например:

print "$_\n" foreach(@files);

вместо:

foreach(@files){
  print "$_\n";
}

Как работает этот синтаксис в следующем, более сложном случае:

die("Not a file: $_") unless -f $_ foreach(@files);

Это дает мне синтаксическую ошибку. Я не пытаюсь писать запутанный код, это просто не важная часть в программе, и поэтому я хочу выразить это как можно более кратко.

ОБОБЩЕННЫЕ ОТВЕТЫ: ​​

Я могу принять только один ответ в качестве принятого, но мне больше всего нравятся следующие ответы Криса и Джона.

Этот использует foreach, как я и предполагал, но без syntax error:

-f or die "Not a file: $_" foreach @files;

А следующий, по крайней мере, так же хорош. Мне нравится, что die находится в начале утверждения, потому что именно на это должно быть обращено внимание читателя:

die("Not a file: $_") for grep {!-f} @files;

Ответы [ 7 ]

13 голосов
/ 20 февраля 2009

Просто чтобы быть Perlish (TMTOWTDI) вы можете использовать логическое короткое замыкание:

-f or die "Not a file: $_" foreach @files;

Протестировано на OS X и работает.

В качестве примечания, -f or die выглядит как множество общих open() or die конструкций, которые я вижу в Perl, и все же ( I думаю) показывает намерение линии (до die под определенные условия).

11 голосов
/ 20 февраля 2009

Вы можете использовать ответ @ Brent.Longborough или, если вам действительно нужен постфикс, сделать:

do { die("Not a file: $_") unless -f $_ } foreach(@files);

Тем не менее, я согласен с другими, то, что это «неважная часть», не означает, что лаконичность лучше. Читаемость имеет значение.

7 голосов
/ 20 февраля 2009

Ну, вы, возможно, не намереваетесь написать запутанный код, но я бы сказал, что вы, безусловно, пытаетесь .

Были бы две строки (или даже блок на одной строке, как предполагает Брент. Лонгборо) вместо одной такой плохой? Честно говоря, это причина, по которой я вообще ненавижу пытаться отлаживать / редактировать Perl-код других людей: большое количество людей, пишущих на Perl, похоже, одержимы выполнением почти всего самым «умным» способом вместо того, чтобы делать таким образом, что это легко понять, если кто-то еще читает.

5 голосов
/ 20 февраля 2009

Если тест на наличие ошибок является основной точкой этого кода, возможно, имеет смысл иметь начальное положение в начале строки. Небольшое улучшение было бы использовать grep:

die("Not a file: $_") for grep {!-f} @files;

Но если вы планируете зацикливание файлов по какой-либо другой причине в этой части кода, было бы лучше добавить его в тело цикла.

3 голосов
/ 20 февраля 2009

Если вы не пытаетесь написать запутанный код, то вам не следует пытаться писать его так. Вы берете что-то, что должно быть простым, и затрудняете его понимание.

1 голос
/ 20 сентября 2009

Ты слишком много думаешь. Вот он на одной строчке без акробатики:

 foreach ( @files ) { die( "Not a file!" ) unless -f }

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

Возможно, у вас есть что-то более сложное, и это только пример. В реальном мире это становится еще проще:

not_a_file_die_die_die( \@files );

Затем вы перемещаете все сложные вещи в подпрограмму. Настоящая хитрость заключается в том, чтобы сделать идеи и intent краткими, а не код, реализующий идею. Механика действительно не имеет значения во многих случаях; Вы больше заботитесь о результате. В этих случаях не переживайте из-за механики.

0 голосов
/ 20 февраля 2009

Черт, Джон просто избил меня до grep.

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

В любом случае, вы не можете делать то, что хотите, с модификаторами постфикса, поскольку у вас может быть только одна вещь по обе стороны от них. Таким образом, вы не можете иметь и unless, и foreach. С вершины соответствующего бита perldoc perlsyn:

За любым простым оператором необязательно может следовать модификатор SINGLE непосредственно перед завершающей точкой с запятой (или окончанием блока).

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