私は現在、次のPerlを使用して、変数が定義され、テキストが含まれているかどうかを確認しています。defined
「初期化されていない値」の警告を回避するために、最初に確認する必要があります。
if (defined $name && length $name > 0) {
# do something with $name
}
これを書くためのより良い(おそらくより簡潔な)方法はありますか?
回答:
定義のチェックがよく見られるので、undef値を使用するための警告に対処する必要はありません(Perl 5.10では問題のある変数が表示されます)。
Use of uninitialized value $name in ...
したがって、この警告を回避するために、人々はあらゆる種類のコードを思い付き、そのコードは、風船ガムやダクトテープではなく、ソリューションの重要な部分のように見え始めます。場合によっては、回避しようとしている警告を明示的にオフにして、何をしているかを示す方がよい場合があります。
{
no warnings 'uninitialized';
if( length $name ) {
...
}
}
それ以外の場合は、データの代わりにある種のnull値を使用してください。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
...
}
mobruleが示すように、少し節約するために代わりに以下を使用できます。
if (defined $name && $name ne '') {
# do something with $name
}
定義されたチェックを破棄して、さらに短いものを取得できます。例:
if ($name ne '') {
# do something with $name
}
ただし、が$name
定義されていない場合、ロジックフローは意図したとおりに機能しますが、使用しているwarnings
(そして使用する必要がある)場合は、次の警告が表示されます。
文字列neでの初期化されていない値の使用
したがって、$name
定義されていない可能性がある場合は、その警告を回避するために、何よりもまず定義を確認する必要があります。SinanÜnürが指摘しているように、Scalar :: MoreUtilsを使用すると、次のempty()
方法で、箱から出してすぐにそれを実行するコードを取得できます(定義をチェックしてから長さがゼロをチェックします)。
use Scalar::MoreUtils qw(empty);
if(not empty($name)) {
# do something with $name
}
まず、length
常に負でない数を返すので、
if ( length $name )
そして
if ( length $name > 0 )
同等です。
未定義の値を空の文字列に置き換えても問題が//=
ない場合は、LHSが定義されていない限り、RHSをLHSに割り当てるPerl5.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
、を使用しますdefault
。
length( $name // '' )
。
//
and//=
演算子は、おそらく存在する中で最も有用な特殊演算子です。
length
では、数値ではないものを返すことができるようになりました(ただし、NaNではありません;)
私は変数があるかどうかを気にしない場合にはundef
、または等しい''
、私は通常のようにそれを要約します:
$name = "" unless defined $name;
if($name ne '') {
# do something with $name
}
$name //= "";
て、Sinanが投稿したものとまったく同じにすることができます。
$name ||= "";
undef
と""
、彼女はただ、他の1つを変更し、単一のテストを使用する必要があります。これは、投稿された他のソリューションの方がはるかに優れている一般的なケースでは機能しませんが、この特定のケースでは、きちんとしたコードになります。これを明確にするために、答えを言い換える必要がありますか?
あなたは言えた
$name ne ""
の代わりに
length $name > 0
シンプルでエレガントな方法で繰り返し行うことが常に可能であるとは限りません。
多くのプロジェクトに複製される共通のコードがある場合は、いつも行うことを実行してください。
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
次に、コードでそれを呼び出します。
use My::String::Util qw( is_nonempty );
if ( is_nonempty $name ) {
# do something with $name
}
または、プロトタイプに反対し、追加の親に反対しない場合は、モジュール内のプロトタイプをスキップして、次のように呼び出しますis_nonempty($name)
。
Scalar::MoreUtils
。
&
関数を呼び出すときにsigilの使用を引き続き推奨しています。ですから、私はすべての作業をプロトタイプに頼らない傾向があります。エラーメッセージに「本当に意味がない限り、サブコールで&sigilの使用をやめる」を追加できると思います。
優れたライブラリType :: Tinyは、Perlコードに型チェックを組み込むためのフレームワークを提供します。ここで示すのは、氷山の最も薄い先端であり、Type :: Tinyを最も単純で手動の方法で使用しています。
詳細については、Type :: Tiny :: Manualを確認してください。
use Types::Common::String qw< NonEmptyStr >;
if ( NonEmptyStr->check($name) ) {
# Do something here.
}
NonEmptyStr->($name); # Throw an exception if validation fails
どうですか
if (length ($name || '')) {
# do something with $name
}
これは元のバージョンとまったく同じではありません。次の場合にもfalseが返されるためです。 $name
数値0または文字列のが、'0'
それ以外の場合はすべて同じように動作します。
perl 5.10(またはそれ以降)では、適切なアプローチは、代わりに定義済みまたは演算子を使用することです。
use feature ':5.10';
if (length ($name // '')) {
# do something with $name
}
これは$name
、trueかどうかではなく、定義されているかどうかに基づいて長さを取得する対象を決定するため、0 /'0'
はこれらのケースを正しく処理しますが、多くの人が利用できるよりも新しいバージョンのperlが必要です。
length undef
は、警告して0を返す代わりに、undefを返します。ブールコンテキストでは、undefは0と同じようにfalseであるため、v5.12以降をターゲットにしている場合は、次のように記述できますif (length $name) { ... }