给定 - 当陈述没有正常工作时('学习Perl'第15章问题)

时间:2017-12-15 07:45:44

标签: perl

使用" Learning Perl"的第15章中给出的给定时间语句的示例书不能正常工作。 我使用的是Perl v5.22.1。我尝试重现以下代码(参见"学习Perl"第五版,第227页。):

    use 5.010;
    given ($ARGV[0])
    {
       when(/fred/i) {say "Name has fred in it"; continue}
       when(/^Fred/) {say "Name starts with Fred"; continue}
       when('Fred')  {say "Name is Fred";}
       default {say "I don't see a Fred"}
    }

当我运行脚本时,我得到以下结果:

D:\>Perl D:\Perl\Example113.pl Frederick
given is experimental at D:\Perl\Example113.pl line 5.
when is experimental at D:\Perl\Example113.pl line 7.
when is experimental at D:\Perl\Example113.pl line 8.
when is experimental at D:\Perl\Example113.pl line 9.
Name has fred in it
Name starts with Fred
I don't see a Fred

正如您所看到的,默认块的工作方式与预期相反。 同时,如果你交换了第一个和最后一个块'当'时,它的工作方式几乎与书中描述的一样:

    use 5.010;
    given ($ARGV[0])
    {
       when('Fred')  {say "Name is Fred"; continue}
       when(/^Fred/) {say "Name starts with Fred"; continue}
       when(/fred/i) {say "Name has fred in it"; }
       default {say "I don't see a Fred"}
    }

是什么给了我们下一个输出:

D:\>Perl D:\Perl\Example113.pl Frederick
given is experimental at D:\Perl\Example113.pl line 5.
when is experimental at D:\Perl\Example113.pl line 7.
when is experimental at D:\Perl\Example113.pl line 8.
when is experimental at D:\Perl\Example113.pl line 9.
Name starts with Fred
Name has fred in it

我做错了什么或在书中是不正确的例子?

2 个答案:

答案 0 :(得分:5)

首先,虽然探索和游戏很好,但我必须重复perlsyn says

  

如前所述,“切换”功能被认为是高度的     实验;它很快就会发生变化。

如果这还不够,可以稍早一点in perlsyn

  

when EXPR 参数确实很难描述       确切地说,但总的来说,它试图猜测你想要做什么。有时       它被解释为$_ ~~ EXPR,有时却没有。它也是       当被given块词汇包围时,它的行为会有所不同       由foreach循环动态包含时。规则也很远       这里难以理解。稍后请参阅Experimental Details on given and when

我不知道如何看待“很难准确描述”的功能。另请注意“大部分功能来自隐式智能匹配”(同一页面)。重要的是,这个改变,而且非常可能显着。

清除之后,您展示的行为是预期的。来自example in perlsyn

given ($foo) {
    when (undef) {
        say '$foo is undefined';
    }
    when ("foo") {
       say '$foo is the string "foo"';
    }
    ...
}

其中$foo 等于字符串"foo",不匹配;这不是正则表达式匹配,而是字符串相等。

在您的示例中,字符串 'Fred' Frederick不相等。在第二个中有continue,所以它确实进入下一个分支,但在第一个分支中没有(虽然它也是default之前的最后一个分支)。使用输入Fred运行程序以查看。

答案 1 :(得分:1)

如果不continuewhendefault退出周围的given或移至周围for的下一个项目。

使用continue,执行下一个语句。

到达时无条件执行default块。

例如,

given ($ARGV[0]) {
    say "Checking for 'x'";
    when (/x/) { say 'contains an x'; continue; }
    say "Checking for 'y'";
    when (/y/) { say 'contains a y';            }
    default    { say 'does not contain a y';    }
}

y

Checking for 'x'
Checking for 'y'
contains a y

x

Checking for 'x'
contains an x
Checking for 'y'
does not contain a y

xy

Checking for 'x'
contains an x
Checking for 'y'
contains a y