Вы могли бы хотеть посмотреть здесь и здесь .
Немного примера кода из первой ссылки:
'0385503954');
// define path to server application
$serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter';
//define method namespace
$namespace="urn:xmethods-BNPriceCheck";
// create client object
$client = new soapclient($serverpath);
// make the call
$price = $client->call('getPrice',$param,$namespace);
// if a fault occurred, output error info
if (isset($fault)) {
print "Error: ". $fault;
}
else if ($price == -1) {
print "The book is not in the database.";
} else {
// otherwise output the result
print "The price of book number ". $param[isbn] ." is $". $price;
}
// kill object
unset($client);
?>
Вы часто видите проверку на определенность, поэтому вам не нужно иметь дело с предупреждением об использовании значения undef (а в Perl 5.10 он сообщает вам ошибочную переменную):
Use of uninitialized value $name in ...
Итак , чтобы обойти это предупреждение, люди придумывают всевозможные коды, и этот код начинает выглядеть как важная часть решения, а не как жевательная резинка и клейкая лента. Иногда лучше показать, что вы делаете, явно отключив предупреждение, которого вы пытаетесь избежать:
{
no warnings 'uninitialized';
if( length $name ) {
...
}
}
В других случаях используйте какое-то нулевое значение вместо данных. С помощью оператора defined-or Perl 5.10 вы можете указать length
явную пустую строку (определенную и вернуть нулевую длину) вместо переменной, которая вызовет предупреждение:
use 5.010;
if( length( $name // '' ) ) {
...
}
В Perl 5.12 это ' немного проще, потому что length
для неопределенного значения также возвращает undefined . Это может показаться немного глупым, но это нравится математику, которым я, возможно, хотел бы быть. Это не вызывает предупреждения, поэтому этот вопрос существует.
use 5.012;
use warnings;
my $name;
if( length $name ) { # no warning
...
}
Во-первых, поскольку length
всегда возвращает неотрицательное число,
if ( length $name )
и
if ( length $name > 0 )
эквивалентны.
Если вы согласны с заменой неопределенного значения пустой строкой, вы можете использовать оператор Perl 5.10 // =
, который присваивает правую часть левой, если не определена левая:
#!/usr/bin/perl
use feature qw( say );
use strict; use warnings;
my $name;
say 'nonempty' if length($name //= '');
say "'$name'";
Обратите внимание на отсутствие предупреждений о неинициализированной переменной, поскольку $ name
присваивается пустая строка, если она не определена.
Однако, если вы не хотите зависеть от установки 5.10, используйте функции, предоставляемые Scalar :: MoreUtils . Например, приведенное выше может быть записано как:
#!/usr/bin/perl
use strict; use warnings;
use Scalar::MoreUtils qw( define );
my $name;
print "nonempty\n" if length($name = define $name);
print "'$name'\n";
Если вы не хотите тупить $ name
, используйте по умолчанию
.
Вы могли бы сказать
$name ne ""
вместо
length $name > 0
В случаях, когда я не Меня не волнует, является ли переменная undef
или равна ''
, я обычно резюмирую ее как:
$name = "" unless defined $name;
if($name ne '') {
# do something with $name
}
Не всегда возможно делать повторяющиеся вещи простым и элегантным способом.
Просто делайте то, что вы всегда делаете, когда у вас есть общий код, который копируется во многих проектах:
Выполните поиск по CPAN, возможно, у кого-то уже есть код для вас. Для этой проблемы я нашел Scalar :: MoreUtils .
Если вы не найдете что-то, что вам нравится на CPAN, создайте модуль и поместите код в подпрограмму:
package My::String::Util;
use strict;
use warnings;
our @ISA = qw( Exporter );
our @EXPORT = ();
our @EXPORT_OK = qw( is_nonempty);
use Carp qw(croak);
sub is_nonempty ($) {
croak "is_nonempty() requires an argument"
unless @_ == 1;
no warnings 'uninitialized';
return( defined $_[0] and length $_[0] != 0 );
}
1;
=head1 BOILERPLATE POD
blah blah blah
=head3 is_nonempty
Returns true if the argument is defined and has non-zero length.
More boilerplate POD.
=cut
Затем в коде вызовите it:
use My::String::Util qw( is_nonempty );
if ( is_nonempty $name ) {
# do something with $name
}
Или, если вы возражаете против прототипов и не возражаете против дополнительных скобок, пропустите прототип в модуле и назовите его так: is_nonempty ($ name)
.
Как насчет
if (length ($name || '')) {
# do something with $name
}
Это не совсем эквивалент вашей исходной версии, так как он также вернет false, если $ name
будет числовое значение 0 или строка '0'
, но будет вести себя одинаково во всех других случаях.
В Perl 5.10 (или новее) подходящим подходом было бы использование оператора defined-or вместо этого:
use feature ':5.10';
if (length ($name // '')) {
# do something with $name
}
Это будет решать, какую длину получить, в зависимости от того, определено ли $ name
, а не от того, истинно ли оно, поэтому 0 / '0'
будет обрабатывать эти случаи правильно, но для этого требуется более свежая версия perl, чем есть у многих.
Как указывает мобрул, вы можете использовать вместо этого для небольшой экономии:
if (defined $name && $name ne '') {
# do something with $name
}
Вы можете отказаться от определенной проверки и получить что-то еще более короткое, например:
if ($name ne '') {
# do something with $name
}
Но в случае, когда $ name
не определено, хотя логический поток будет работать так, как задумано, если вы используете предупреждения
(а вы должны использовать), то вы получите следующее предупреждение:
Use of uninitialized value in string ne
Итак, если есть вероятность, что $ name
не может быть определено, вам действительно нужно в первую очередь проверить определенность, чтобы избежать этого предупреждения. Как указывает Синан Унюр, вы можете использовать Scalar :: MoreUtils , чтобы получить код, который делает именно это (проверяет определенность, затем проверяет нулевую длину) из коробки, с помощью empty ()
метод:
use Scalar::MoreUtils qw(empty);
if(not empty($name)) {
# do something with $name
}
if ($name ) { #since undef and '' both evaluate to false #this should work only when string is defined and non-empty... #unless you're expecting someting like $name="0" which is false. #notice though that $name="00" is not false }