0

我尝试使用Perl 的给定 / when 构造作为子例程中的表达式,它在某些情况下应该返回一个包含一些警告的字符串,否则返回一个空字符串:

sub warn_about_invalid_date {
    my ( $date ) = @_;
    return do {
        given ($date) { # <------------ works only with given, does not with for
            when (not /^\d{4}-\d{2}-\d{2}$/) {
                'Invalid date format (should be YYYY-MM-DD)';
            }
            when ('0001-01-01') {
                'Use of default date "0001-01-01"';
            }
            when ($_ lt '1900-01-01') {
                'Probably too far in the past (year < 1900)';
            }
            when ($_ gt '2100-01-01') {
                'Probably too far in the future (year > 2100)';
            }
            default {
                '';
            }
        }
    };
}

return do { }(请忽略每个表达式末尾的一些冗余/冗长/非惯用的 Perl 代码或分号,这些是我公司的编码实践。)

但是,因为我尝试遵循 Perl 的良好实践,以及来自 brian d foy 的Effective Perl的这些,这里使用 for() 而不是 given(),所以我在上面的代码段中交换givenfor......它没有作为我期望。任何输入的返回值总是''(空字符串/假)。

我已将问题缩小到这种情况:

use v5.10.1;
use strict;
use warnings;
use Data::Dumper;

sub test_for {
    for (shift) {
        when (1) { 'True' }
        default  { 'False' }
    }
}

sub test_given {
    given (shift) {
        when (1) { 'True' }
        default  { 'False' }
    }
}

sub test_if {
    if (shift) { 'True' }
    else  { 'False' }
}

sub test_given_if {
    given (shift) {
        if ($_) { 'True' }
        else  { 'False' }
    }
}

sub test_for_if {
    for (shift) {
        if ($_) { 'True' }
        else  { 'False' }
    }
}

$Data::Dumper::Indent = 0;
$Data::Dumper::Terse = 1;
say "test_for( $_ ): ", Dumper test_for($_) for 0..1;
say "test_given( $_ ): ", Dumper test_given($_) for 0..1;
say "test_if( $_ ): ", Dumper test_if($_) for 0..1;
say "test_for_if( $_ ): ", Dumper test_for_if($_) for 0..1;
say "test_given_if( $_ ): ", Dumper test_given_if($_) for 0..1;

哪个输出

perl-5.10.1
==========
Useless use of a constant in void context at /home/grozn/test3a.pl line 9.
Useless use of a constant in void context at /home/grozn/test3a.pl line 16.
Useless use of a constant in void context at /home/grozn/test3a.pl line 35.
Useless use of a constant in void context at /home/grozn/test3a.pl line 36.
Useless use of a constant in void context at /home/grozn/test3a.pl line 42.
test_for( 0 ): ''
test_for( 1 ): ''
test_given( 0 ): 
test_given( 1 ): 
test_if( 0 ): 'False'
test_if( 1 ): 'True'
test_for_if( 0 ): ''
test_for_if( 1 ): ''
test_given_if( 0 ): 
test_given_if( 1 ): 
test_for_constant( 0 ): ''
test_for_constant( 1 ): ''


perl-5.16
==========
Useless use of a constant ("True") in void context at /home/grozn/test3a.pl line 35.
Useless use of a constant ("False") in void context at /home/grozn/test3a.pl line 36.
Useless use of a constant ("Foo") in void context at /home/grozn/test3a.pl line 42.
test_for( 0 ): ''
test_for( 1 ): ''
test_given( 0 ): 'False'
test_given( 1 ): 'True'
test_if( 0 ): 'False'
test_if( 1 ): 'True'
test_for_if( 0 ): ''
test_for_if( 1 ): ''
test_given_if( 0 ): 'False'
test_given_if( 1 ): 'True'
test_for_constant( 0 ): ''
test_for_constant( 1 ): ''


perl-5.18
==========
when is experimental at /home/grozn/test3a.pl line 9.
given is experimental at /home/grozn/test3a.pl line 15.
when is experimental at /home/grozn/test3a.pl line 16.
given is experimental at /home/grozn/test3a.pl line 27.
Useless use of a constant ("True") in void context at /home/grozn/test3a.pl line 35.
Useless use of a constant ("False") in void context at /home/grozn/test3a.pl line 36.
Useless use of a constant ("Foo") in void context at /home/grozn/test3a.pl line 42.
test_for( 0 ): ''
test_for( 1 ): ''
test_given( 0 ): 'False'
test_given( 1 ): 'True'
test_if( 0 ): 'False'
test_if( 1 ): 'True'
test_for_if( 0 ): ''
test_for_if( 1 ): ''
test_given_if( 0 ): 'False'
test_given_if( 1 ): 'True'
test_for_constant( 0 ): ''
test_for_constant( 1 ): ''

test_for_if
从 perls 5.10.1、5.16.3 和 5.18.1 执行时(警告指向) 。

我的问题是:

这是for/when表达的正确行为吗?它并没有这样隐含地记录(Given / when 的“返回值”小节在“Experimental Details on given and when”部分中,并且仅提及),但据我所知for,它是given(for应该和given这里一样好的外用剂,不应该吗?)。

如果这是一个正确的行为,那么是否有任何理由使用for而不是在修复如何对待given的 Perl 5.18 中使用?或者我应该在 Perl 的文档中填写错误/发送拉取请求?given$_

如果它坏了,我是否应该在 Perl 中填充一个错误(我的意思是我应该始终将for其视为given更全面的孪生兄弟)?

编辑:

我在choroba 的回答和评论if之后添加了三个案例,其中他认为行为与and company相同。在那之后我变得更加困惑。forif

4

1 回答 1

2

将缺少return的 s 添加到test_for子例程中以获得相同的行为。given返回最后一个计算的表达式的值,for不返回。

于 2013-08-20T15:32:05.637 回答