switch-和if-语句之间的差异

时间:2010-11-29 08:46:27

标签: perl if-statement switch-statement

这两个陈述的行为是否相同,还是会产生不同的结果?

if ( ... ) {...}
elsif( ... ) {... }
elsif( ... ) { ... }
else { ... }

given ( ... ) {
    when ( ... ) { ... }
    when ( ... ) { ... }
    default { ... }
}

我发现了问题 - 修改后的第九个“当”它现在有效。

...
no warnings qw(numeric);
my $c = &getch();

given ( $c ) {
when ( $c == $KEY_LEFT and 1 > 0 ) { say 1; say $c }
when ( $c == $KEY_RIGHT ) { say 2; say $c } 
when ( $c eq "\cH" or $c eq "\c?" ) { say 3; say $c } 
when ( $c eq "\cC" ) { say 4; say $c } 
when ( $c eq "\cX" or $c eq "\cD" ) { say 5; say $c } 
when ( $c eq "\cA" ) { say 6; say $c } 
when ( $c eq "\cE" ) { say 7; say $c } 
when ( $c eq "\cL" ) { say 8; say $c } 
when ( not( not $SpecialKey{$c} ) ) { say 9; say $c } 
when ( ord( $c ) >= 32 ) { say 10; say $c } 
default { say 11; say $c }
}

if ( $c == $KEY_LEFT and 1 > 0 ) { say 1; say $c }
elsif ( $c == $KEY_RIGHT ) { say 2; say $c } 
elsif ( $c eq "\cH" or $c eq "\c?" ) { say 3; say $c } 
elsif ( $c eq "\cC" ) { say 4; say $c } 
elsif ( $c eq "\cX" or $c eq "\cD" ) { say 5; say $c } 
elsif ( $c eq "\cA" ) { say 6; say $c } 
elsif ( $c eq "\cE" ) { say 7; say $c } 
elsif ( $c eq "\cL" ) { say 8; say $c } 
elsif ( $SpecialKey{$c} ) { say 9; say $c } 
elsif ( ord( $c ) >= 32 ) { say 10; say $c } 
else { say 11; say $c }

close TTYIN;

5 个答案:

答案 0 :(得分:4)

你所谓的“固定”版本现在在两个版本的代码中做了不同的事情。检查哈希中是否存在密钥与检查相关值是否为真完全不同。

您可以从散列中获取三个不同的真值 - 散列中是否存在密钥,是否定义了关联值以及关联值是true还是false。这段代码应该证明三者之间的区别:

#!/usr/bin/perl

use strict;
use warnings;

my %hash = (
  key1 => undef,
  key2 => 0,
  key3 => 1,
);

foreach (qw(key1 key2 key3 key4)) {
  check_key($_);
}

sub check_key {
  my $k = shift;

  print "Key $k ";
  if (exists $hash{$k}) {
    print 'exists. ';
  } else {
    print "doesn't exist. ";
  }

  print 'Value ';

  if (defined $hash{$k}) {
    print 'is defined ';
  } else {
    print 'is not defined ';
  }

  print 'and is ';

  if ($hash{$k}) {
    print "true\n";
  } else {
    print "false\n";
  }
}

答案 1 :(得分:4)

无论您使用given/when做什么,都可以使用if/elsif/else。我们的想法是when/given被认为更容易阅读,并且默认情况下可以自动使用 smartmatching ,而您必须使用if/else语句指定智能匹配。

我没有解析您的代码以确保它们完全相同,但看起来您对if/elsif/elsegiven/when或多或少有正确的想法。

我从未真正理解对所谓的 switch语句的渴望。这是Perl程序员总是抱怨的东西 - 在Perl中缺少 switch语句。也许这是大多数Perl开发人员深情记忆的C事物。但我从未发现if/elsif/else陈述不好。

让我感到困惑的是,当他们最终实现 switch语句时,他们没有将其称为switch。为什么不呢?

为什么say代替printnl

而且,为什么lastnext代替breakcontinue。为什么不简单地使用其他语言已经使用的标准名称?

但这足以让Seinfeld的风格抱怨......

正如davorg所说,不存在的哈希密钥,存在但未定义的哈希密钥,以及已定义的哈希密钥,但被评估为假的哈希密钥之间存在很大差异:

例如:

use strict;
use warnings;
no warnings qw(uninitialized);

my %hash;
$hash{FOO} = "bar";

if (not exists($hash{BAR})) {
print "\$hash{FOO} doesn't exist\n";
}
if (not defined($hash{BAR})) {
print "\$hash{BAR} is undefined\n";
}
if (not $hash{BAR}) {
print "\$hash{BAR} evaluates to false\n";
}
if ($hash{BAR} eq undef) {
print "\$hash{BAR} is equal to 'undef'\n";
}

您可以看到$hash{BAR}甚至不作为%hash哈希中的键存在,但它也未定义,并且评估为false。而且,您还可以看到它还评估为undef(请注意我必须设置no warnings qw(uninitialized);以防止它在我的上一个$hash{BAR}语句中抱怨if未初始化

但是,如果我这样做:

$hash{FOO} = bar;
$hash{BAR} = undef;

第一个if语句不再评估为true,因为密钥BAR现在确实存在于哈希中,但该值仍未定义,仍然评估为false

而且,如果我这样做了:

$hash{FOO} = bar;
$hash{BAR} = 0;

$hash{BAR}现在作为%hash中的密钥存在,不再是undefined,但它仍然评估为false

我只想简单地说:

if (not $hash{BAR}) {

因为它短而甜,可能做我想要的。但是,我必须理解哈希中存在键,对false进行评估,而将defined作为三个单独的事物之间的区别。如果您有一个可以返回NULL字符串或零值的子例程,这一点很重要:

if (not foo($bar)) {
    die qq(Error of some sort\n);
}

sub foo {
    $bar = <FOO> or return;
    return chomp($bar);
}

如果我的文件中有一个空行,它将返回一个NULL字符串,但子程序仍将返回一个定义的值。以上可能不会做我想要的。

答案 2 :(得分:1)

添加另一个答案,因为我刚刚意识到真正的问题是什么。

你的“when($ SpecialKey {$ c})”相当于“if($ _ ~~ $ SpecialKey {$ c})”。而且“给定”将$ _设置为$ c,与“if($ c ~~ $ SpecialKey {$ c})”相同。当比较两个标量值(我假设这是我们在这里得到的)时,智能匹配运算符会查找数字值并在适当时使用“eq”或“==”。

因此,您的代码实际上等同于“if($ c == $ SpecialKey {$ c})”。这与“if($ SpecialKey {$ c})”完全不同。

答案 3 :(得分:0)

他们表现得完全平等。

答案 4 :(得分:0)

给定/何时具有隐式智能匹配:

  

大部分权力来自隐式智能匹配:

     
    
        
  1. 当($富)
  2.        
     

完全等同于

     
    
        
  1. 何时($ _ ~~ $ foo)
  2.        

我不认为/ else是否会这样做(?)

请参阅perlsyn

编辑: 当使用给定/当OP的方式时,猜测这并不重要,但它仍然回答了问题:)