#!/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";
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
}
use Types::Common::String qw< NonEmptyStr >;
if ( NonEmptyStr->check($name) ) {
# Do something here.
}
NonEmptyStr->($name); # Throw an exception if validation fails
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
}
9条答案
按热度按时间2sbarzqh1#
您经常会看到对已定义性的检查,因此不必处理使用undef值时的警告(在Perl 5.10中,它会告诉您违规的变量):
因此,为了避开这个警告,人们想出了各种各样的代码,这些代码开始看起来像是解决方案的重要组成部分,而不是像泡泡糖和胶带一样。有时候,最好通过明确关闭你试图避免的警告来显示你正在做什么:
在其他情况下,使用某种空值代替实际数据可以解决这个问题。对于Perl 5.10's defined-or operator,给予
length
一个显式的空字符串(已定义,并返回零长度),而不是触发警告的变量:在Perl 5.12中,这要简单一些,因为
length
on an undefined value also returns undefined。这可能看起来有点愚蠢,但这让我想成为的数学家感到高兴。这不会发出警告,这就是这个问题存在的原因。kyvafyod2#
正如mobrule所指出的,您可以使用下面的代码来节省一小笔费用:
您可以丢弃已定义的检查,并获得更短的内容,例如:
但是,在没有定义
$name
的情况下,尽管逻辑流将按预期工作,但如果您使用warnings
(您应该使用warnings
),那么您将得到以下警告:所以,如果
$name
可能没有定义,你真的需要首先检查定义性,以避免警告。正如希南Ünür指出的,你可以使用Scalar::MoreUtils通过empty()
方法获得开箱即用的代码(检查定义性,然后检查零长度):aemubtdh3#
首先,由于
length
总是返回一个非负数,以及
是等效的。
如果可以用空字符串替换未定义的值,则可以使用Perl 5.10的
//=
操作符,该操作符将RHS分配给LHS,除非定义了LHS:请注意,没有关于未初始化变量的警告,因为如果
$name
未定义,它将被赋为空字符串。但是,如果您不希望依赖于正在安装的5.10,请使用Scalar::MoreUtils提供的函数。例如,上面的代码可以写成:
如果不想击败
$name
,请使用default
。afdcj2ne4#
在我不关心变量是
undef
还是等于''
的情况下,我通常将其总结为:axr492tv5#
你可以说
代替
uajslkp66#
用简单优雅的方式做重复的事情并不总是可能的。
当您有跨多个项目复制的公共代码时,只需执行您经常执行的操作:
搜索CPAN,有人可能已经有了你的代码。对于这个问题,我找到了Scalar::MoreUtils。
如果你在CPAN上找不到你喜欢的东西,那么就创建一个模块,并将代码放入子例程中:
然后在代码中调用它:
或者,如果你反对prototype,但不反对额外的括号,那么就跳过模块中的prototype,像这样调用它:
is_nonempty($name)
.6qfn3psc7#
优秀的库Type::Tiny提供了一个框架,可以利用它将类型检查构建到Perl代码中,我在这里展示的只是冰山一角,并且是以最简单和手动的方式使用Type::Tiny。
请务必查看Type::Tiny::Manual以了解更多信息。
6qftjkof8#
不如
这并不完全等同于原始版本,因为如果
$name
是数值0或字符串'0'
,它也将返回false,但在所有其他情况下的行为相同。在perl 5.10(或更高版本)中,适当的方法是使用defined-or操作符:
这将根据
$name
是否被定义而不是它是否为真来决定获取什么长度,所以0/'0'
将正确处理这些情况,但是它需要一个更新的perl版本,比许多人所能获得的版本都要高。tgabmvqs9#