我对perl中的比较表达式的值感到困惑:
print "why... ",1>2, "\n";
我得到以下结果:
why...
那么,为什么" 1> 2"的结果呢?是空的 ?这本书告诉我" $ a> $ b"是0或1。
答案 0 :(得分:4)
好的,给自己一杯咖啡,因为是时候沿着perl的兔子洞走了dualvars.
这里发生的事情是 - perl使用'boolean'值结果做了一些魔术。
正如您所知 - 在perl中,“false”(几乎)是评估为零或空字符串的任何内容。
所以0
是假的,但''
(以及其他一些东西)也是如此。
Perl通常从上下文中推断出来,而魔术“只是起作用”。
print "yes" if 1>2; #just works.
但是......打印布尔结果怎么样?好吧,事实证明,因为它可能是 “空字符串”或“0”perl创建一个双变量。
这特别是具有两个值的东西。
#!/usr/bin/env perl
use strict;
use warnings;
use Scalar::Util qw ( isdual dualvar );
my $result = 1>2;
if ( isdual ( $result ) ) {
print "\$result is a dualvar\n";
}
print "Number:", 0+$result,"\n";
print "String:",''.$result,"\n";
如果您在正常值上尝试了这些操作:
my $number = '';
print 0+$number;
你会得到
Argument "" isn't numeric in addition (+)
您可以使用dualvar
:
my $thing = dualvar ( 666, "the beast" );
print 0+$thing,"\n";
print $thing,"\n";
大多数情况下你不需要 - 如果你干涉太多,这就是可以做很奇怪的事情。但通常“结果”是双重的,例如$@
和$!
。
open ( my $fh, '<', "not_here"); #generates $!
print "\$! is dual\n" if isdual ( $! );
print 0+$!,"\n";
print $!,"\n
打印:
$! is dual
2
No such file or directory
在你的问题的背景下 - 这是因为空字符串或零是'假'而perl不知道你需要什么样的'假'。所以它给你们两个。
因为你正在做一个print
perl决定你现在正在使用字符串,并使用双变量的字符串部分 - 空字符串。
你可以这样做:
print "why... ",0+(1>2), "\n";
添加零会强制切换到'数字',并为您提供:
why... 0
但它的长短确实是 - 不要做你正在做的事情,这是糟糕的风格。如果某些东西是假的,你需要一个特定的值 - 然后拼出那个值是什么。没有错:
return 0 if 1>2;
或者:
print "Why: ", 1>2 ? "1" : "0", "\n";
答案 1 :(得分:2)
我鼓掌Sobrique's explanation of dualvars但我并不认为有必要让Perl的这些深奥部分来解决您的问题
Perl的双变量比你想象的要常见得多,主要用于避免重复字符串和整数之间的转换
my $v1 = "10";
my $v2 = $v1 + 20;
在此示例中,变量$v1
设置为字符串"10"
。该字符串必须转换为整数才能执行下一个操作,即添加数字20
并将结果存储在$v2
中。如果再次需要$v1
的数字版本,为了避免重复转换,它将成为 dualvar ,它同时包含字符串和数值,并计算为"10"
或10
根据其使用方式
所有这些都是Perl
中的 false数值零
字符串 "0"
(请注意,评估为数字零的任何其他字符串,例如"0.0"
或"0E99"
, true )
空字符串""
undef
空列表( )
其他任何事情都是真的,所以只要符合这些规则,子程序和表达式就可以为布尔值返回几乎任何东西。在实践中,Perl内置运算符通常返回 false 的固定值,该值恰好是 dualvar 等于零作为数字而空字符串作为字符串
由于这个表达,我有上述问题:
$index = (($index - $kIntervals) >> ($index > $kIntervals)) + $kIntervals
当
$index
&lt;$kIntervals
,我得到一个奇怪的结果(对我来说)。也许最后的原因是班次操作员
此处,值$index > $kIntervals
用作数字,因此其值将为零或一个预期值。我不知道你想从这个表达式得到什么结果,但<<
将执行逻辑移位并将第一个操作数视为一个简单的位模式。如果你想进行算术移位,这基本上乘以2的幂,那么你需要暂时启用use integer
,就像这样
$index = do {
use integer;
( ( $index - $kIntervals ) >> ( $index > $kIntervals ) ) + $kIntervals;
};
但由于我不知道你在做什么,这很可能是错误的