可以使用switch/case或given/when来模拟这个Perl行为吗?

ste*_*rie 1 perl

我想知道是否有人有任何关于改进以下代码的建议(如果可能的话),以便它不需要重复(我的@a = $ time =〜...),可能使用case/switch或given/when或还有一些我想念的想法?

my $time = '12:59pm';

if( my @a = $time =~ m/^(\d\d?)(am|pm)$/ )        { tell_time( $a[0], 0, $a[1] ) }
if( my @a = $time =~ m/^(\d\d?):(\d\d)(am|pm)$/ ) { tell_time( @a ) }
if( my @a = $time =~ m/^(\d\d?):(\d\d)$/ )        { tell_time( @a ) }

sub tell_time
{
    my $hour    = shift;
    my $minute  = shift || '00';
    my $ampm    = shift || ( $hour > 12 ) ? 'pm' : 'am';

    print "Hour: $hour, Minute: $minute, AMPM: $ampm\n";
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试过使用Switch和5.10给定/何时但似乎无法做到这样的事情:

given( $time )
{
    when( /^(\d\d?)(am|pm)$/ )        { tell_time( $_[0], 0, $_[1] ) }
    when( /^(\d\d?):(\d\d)(am|pm)$/ ) { tell_time( @_ ) }
    when( /^(\d\d?):(\d\d)$/ )        { tell_time( @_ ) }
}
Run Code Online (Sandbox Code Playgroud)

这不会飞,因为@_似乎存储了$ time.

另请注意,我对问题的语法比代码解决的问题更感兴趣.我很清楚我可以使用Time :: ParseDate来找出格式化为时间或日期的字符串的各个部分.

Chr*_*utz 10

您的正则表达式用于()提取匹配项,但您不必将它们存储在数组中.如果你想,他们在存储$1,$2,$3,等等.Lookie:

given( $time )
{
    when( /^(\d\d?)(am|pm)$/ )        { tell_time( $1, 0, $2 ) }
    when( /^(\d\d?):(\d\d)(am|pm)$/ ) { tell_time( $1, $2, $3 ) }
    when( /^(\d\d?):(\d\d)$/ )        { tell_time( $1, $2 ) }
}
Run Code Online (Sandbox Code Playgroud)

完全符合我的想法.

如果你想添加语法,我会写tell_time()简单地把时间作为一个字符串,并让函数解析结果本身,而不是让你的代码的用户自己解析它.或者,您可以使用此given()块作为新函数的开头,它正好执行此操作 - 解析时间字符串并将其正确传递给tell_time().但那只是我.我不知道你需要你的代码做什么,所以一定要去做.