perl

时间:2017-05-26 08:24:48

标签: perl

我对perl中的比较表达式的值感到困惑:

   print "why... ",1>2, "\n";

我得到以下结果:

   why...

那么,为什么" 1> 2"的结果呢?是空的 ?这本书告诉我" $ a> $ b"是0或1。

2 个答案:

答案 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;
};

但由于我不知道你在做什么,这很可能是错误的