Я большой сторонник читабельности, а не краткости.Perl довольно хорошо оптимизирует ваш код, так что вам не нужно об этом беспокоиться.Не беспокойтесь о количестве строк и сохраняйте код читабельным.Все, что вы сохраняете (если вы что-то сохраняете) в ЦП, будет потрачено впустую на время и ошибки, возникающие при попытке сохранить трудно читаемую программу.
В этом отношении:
- Не используйте пост-суффиксные
if
операторы, если это не что-то очень простое, например next if (s/^\s*$/);
. - Используйте имена переменных и не зависят от
$_
. - Используйте пробелы после запятых.
Кроме того, я бы добавил:
- Не бойтесь добавлять круглые скобки, если они помогают уточнить, что вы делаете.Я склонен использовать круглые скобки, если функции имеют более двух аргументов, просто чтобы помочь удерживать аргументы вместе:
Например:
open my $foo, "<", $bar or die qq(This is the end!\n);
против
open (my $foo, "<", $bar) or die qq(This is the end!\n);
Теперь более очевидно, какая часть строки является параметрами в функции open
.
Строка, которой я менее всего взволнован:
if (defined($x) && defined($y) && defined($val) && defined($err)){
Что не так с этой строкой?Совершенно ясно, что вы пытаетесь сказать.Я бы использовал немного более современный синтаксис и добавил бы некоторые круглые скобки, чтобы помочь перегруппировке, чтобы сделать ее более понятной:
if ((defined $x) and (defined $y) and (defined $val) and (defined $err)) {
Глядя на то, что вы делаете, я бы немного изменил положение вещей ...
#! /usr/bin/env perl
use strict;
use warnings;
use features qw(say);
say "X, Y, Val";
for my $filename (<>) {
open (my $log, "<", $filename) or die $!;
my ($x, $y, $value, $err);
while (chomp (my $coord_line = <$log>)) {
if ($coord_line =~ /\((-?[0-9]+),(-?[0-9])\)/) {
($x, $y) = ($1, $2);
}
elsif ($coord_line =~ /^Results.*\((.*),(.*)\)$/) {
($val, $err) = ($1, $2);
say "$x, $y, $val:$err";
}
}
}
}
Обратите внимание, я сейчас просто проверяю строку один раз.И обратите внимание, что я печатаю, когда получаю результат, который устраняет необходимость проверки, установлены ли все переменные.
Также обратите внимание, что вам не нужно ARGV::readonly
, потому что вы используете более двух параметровв функции open
.В этом случае открытие файла ls|
не вызовет никаких проблем.Проблема возникает только тогда, когда в вашем операторе open
есть только два параметра.
В вышеприведенной программе предполагается, что у вас есть только координаты и результаты или строки мусора.Однако, если у вас несколько координат, AND , вам нужен только первый набор, вам придется их отслеживать.Я рекомендую использовать для этой цели отдельную переменную, и вы можете использовать константы, чтобы уточнить, что вы делаете:
#! /usr/bin/env perl
use strict;
use warnings;
use features qw(say);
use autodie;
use constants {
SET => 1,
NOT_SET => 0,
};
say "X, Y, Val";
for my $filename (<>) {
if (not open my $log, "<", $filename) {
warn qq(Cannot open file "$filename": $!);
next;
}
my ($x, $y, $value, $err);
my $coordinates = NOT_SET;
while (my chomp($coord_line = <$log>)) {
if ($coord_line =~ /\((-?[0-9]+),(-?[0-9])\)/) {
if ($coordinates == NOT_SET)) {
($x, $y) = ($1, $2);
$coordinates = SET;
}
}
elsif ($coord_line =~ /^Results.*\((.*),(.*)\)$/) {
($val, $err) = ($1, $2);
say "$x, $y, $val:$err";
$coordinates = NOT_SET;
}
}
}
Используя оператор if/elsif
, вы теперьпроверять каждую строку только один раз.Это также позволяет пользователям знать, что каждая строка является либо координатной, либо строкой результата, и что одна строка не является одновременно.В вашей исходной программе вы проверяете каждую строку для обеих, поэтому не было ясно, может ли одна строка быть и тем и другим.
Я также не умираю, если файл не может быть открыт.Вместо этого я печатаю предупреждение и перехожу к следующему.Вы могли бы сделать в любом случае.(Я умер в первом, но продолжаю пахать вперед во втором).
Кстати, ваши предпочтения относительно того, могут ли первые два оператора if
комбинироваться вместо вложенных.У меня также есть друг, которому не нравится использовать числовые константы, потому что это легко сказать:
if ($ arguments = SET) {
вместо
if($ координаты == SET) {
Если бы у вас было это:
use constants {
SET => "set",
NOT_SET => "",
};
Вы бы привыкли делать это:
if ($coordinates eq SET) {
и нестолкнуться с проблемой =
против ==
.