【问题标题】:What does Perl return when a numeric comparison is false?当数字比较为假时,Perl 会返回什么?
【发布时间】:2015-01-09 15:48:09
【问题描述】:

我正在尝试执行此代码。令我困惑的是,为什么这个比较在 false 时不返回任何值。这是这些比较运算符的默认行为吗?

my $output = (2 <= 1); 
print "value=$output";

当逻辑检查失败时,比较运算符是否会返回undef

【问题讨论】:

  • 您可能会发现 Contextual::Return 很有用且值得一看。它检测操作上下文。

标签: perl


【解决方案1】:

relational operators

返回 1 表示 true 和定义的空字符串的特殊版本 "" ,它算作零,但不会收到有关不正确数字转换的警告,就像 "0 but true" 一样。

你得到的值实际上是一个双变量。它具有单独的数字和字符串值(实际上不是空字符串的特殊版本)。数值为 0,字符串值为空字符串。您使用了字符串部分,它是空的,但 0 仍然存在。您可以使用Devel::Peek 查看变量记录:

use Devel::Peek;
my $result = ( 1 == 2 );
Dump( $result );

在幕后的SV(标量值)这件事中,你看到PV中的字符串值和IV中​​的数值和NV(整数和数值):

SV = PVNV(0x7fe602802750) at 0x7fe603002e70
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x7fe6026016b0 ""\0
  CUR = 0
  LEN = 16

还有其他种类的双变量。例如,$! 错误变量具有错误编号和错误文本(我在Mastering Perl 中谈到了这一点)。这不是您通常需要担心的事情,因为 Perl 为上下文做了正确的事情。

如果您总是想要一个数值,请在数值上下文中使用它:

my $numeric = 0 + $result;   # 0

您可以使用Scalar::Utildualvar 创建自己的双变量,并且可以使用isdual 检查标量是否是双变量。

use Scalar::Util qw(isdual);
my $result = ( 1 == 2 );
print isdual($result) ? "dualvar" : "Not dualvar";

如果您想检查您返回的值是否已定义(您说没有),您可以通过defined 进行检查。但是,定义了一个空字符串。如果要检查它是否不是空字符串,可以使用length。当您拥有的值不可打印时,这些会有所帮助。

【讨论】:

  • 所以双变量性质可以防止数字上下文中的警告?
  • 值得一提:如果您希望自己的函数返回这些特殊的真假值,您可以返回!!1(真)或!!0(假)。
  • @mpapec:在数字上下文中没有警告,因为它不是未初始化的数值。
  • @tobyink 不过这对!!( 2==1 ) 不起作用。你仍然得到空字符串。这就是我使用0 + $result的原因。
  • @chidori - Perl 有标量。它们只是单一的值。按照设计,Perl 以操作员想要处理的方式使用单个值。数字运算符需要数字,因此 Perl 有一种方法可以将字符串转换为数字,而不会干扰字符串的表示。这是我们在学习 Perl 开始时讨论的内容。
【解决方案2】:

布尔运算符在 true 时返回 1,在 false 时返回 ''。您正在尝试打印空字符串。

试试这个测试

use strict;
use warnings;
my $output = (2 <= 1); 
print $output ? "value=|$output|" : "value=<$output>";

【讨论】:

  • $output 总是被定义而不是 undef
  • 实际上,Perl 的 false 值是一个特殊的空字符串,在数字上下文中使用时不会产生警告。 (如果在需要数字的地方使用普通的空字符串,则会生成“参数不是数字”警告。)
  • 这不是真的。而且,Perl 没有在数字上下文中使用空字符串。
  • @briandfoy 有趣的是,Data::Dump(er) 和 json 更喜欢字符串而不是数字表示; perl -MJSON -e 'print encode_json([ 1==2 ])'
  • 嗯,JSON 和 Data::Dumper 对数据结构进行字符串化,所以这并不奇怪 :)
【解决方案3】:

Comparisons 可以返回一个特殊的 false 值,它是一个空字符串或 0,具体取决于评估它的上下文。如果您正在寻找 true 和 false 的特定值,使用这样的语句会更安全:

my $output = ( 2 <= 1 ) ? 1 : 0;

以下代码将说明特殊 false 值的行为。

use 5.014; 
say ( 2 <= 1); # prints nothing
my $output = ( 2 <= 1 ) ? 1 : 0; 
say $output; # prints 0
$output = ( 2 > 1 ) ? 1 : 0 ; 
say int $output; # prints 1
say $output; # prints 1
$output = ( 2 <= 1 ) ; 
say int $output ; # prints 0

如果您不熟悉 ? :构造见:http://perldoc.perl.org/perlop.html#Conditional-Operator

【讨论】:

  • int 将所有非数字变为 0,并设置 IV 和 NV 部分以创建双变量。 :)
  • @briandfoy:不确定您在该评论中解决的是什么情况; int 通常设置 IV/UV 或 NV,而不是同时设置
  • 我是说int 对数值比较的结果没有任何特殊的作用。给它'abc',它会返回0,但也会保留'abc'。
  • 关于 int 的好点。我只是在寻找一个快速演示,即错误值在数值上评估为 0。
【解决方案4】:

该表达式返回一个空字符串 (""),Perl 在评估像 ifunless 这样的句子时将其视为错误值。

在 Perl 中,0"0" 和空字符串 ("") 为 false。 undef 也是错误的,但您可能会收到警告。其他都是真的。

【讨论】:

    猜你喜欢
    • 2016-07-08
    • 2022-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2016-10-22
    相关资源
    最近更新 更多