Как я могу отображать неопределенные значения из printf в Perl?
Вопрос
Я ищу элегантный способ обозначения неопределенных значений в ситуациях, когда обычно отображаются форматированные числа.Я придумаю небольшой пример.Для начала вы, конечно, не можете использовать это:
#!/usr/bin/perl
use strict;
use warnings;
for my $s (1, 1.2, undef, 1.3) {
printf "%5.2f\n", $s;
}
... потому что «предупреждения об использовании» прибивают вас к «Использованию неинициализированного значения...» на третьей итерации.Итак, следующий шаг примерно такой:
#!/usr/bin/perl
use strict;
use warnings;
for my $s (1, 1.2, undef, 1.3) {
printf "%5.2f\n", $s//0;
}
И, кстати, мне нравится новый оператор 5.10 '//'?Но на самом деле это не то, чего я хочу, потому что значение $s не равно нулю, оно неопределенно.То, что я действительно хочу, это что-то вроде этого:
#!/usr/bin/perl
use strict;
use warnings;
for my $s (1, 1.2, undef, 1.3) {
printf "%5.2f\n", $s//q();
}
... но я не могу, потому что это создает проблему «Аргумент не числовой...» для третьего значения.
Это подводит меня к порогу моего вопроса.Я, конечно, могу написать код, который проверяет каждое выдаваемое мной число на предмет определенности и создает совершенно другую строку формата printf, не основанную на %f, но, ну... фу.
Кто-нибудь определил хороший способ справиться с требованиями такого типа?
Решение
Я не думаю, что есть что-нибудь фу об этом - это именно то, что вы хотите сделать.
use strict;
use warnings;
my($raw) = [1, 1.2, undef, 1.3];
my($formatted) = [map((defined $_ ? sprintf('%5.2f', $_) : "(undef)"), @$raw)];
print '$formatted: <', join('> <', @{$formatted}), qq(>\n);
Другие советы
Это некрасиво, но я бы просто сделал это так, как
defined($s) ? printf "%f.2f\n", $s : print "undef\n";
я думаю хороший способ состоит в том, чтобы написать/получить универсальный симпатичный принтер, который принимает все, что вы на него бросаете, а затем выполняет:
#!/usr/bin/perl
use strict;
use warnings;
use MyPrettyPrinter;
for my $s (1, 1.2, undef, 1.3) {
print MyPrettyPrinted($s), "\n";
}