给定/何时存在什么样的整洁用例?

时间:2010-09-03 19:21:39

标签: perl switch-statement

Perl 5.10引入了一个带given/when的正确开关构造,它似乎是一个强大的工具。

目前,perldoc perlsyn缺少一些很好的例子。

最近我发现它很方便的一个案例是将它与文件测试操作符一起使用:

given (-d "foo/bar/") {
    when (1) { ... } # defined is wrong as -d returns '' on a file.
    default { ... }
}

或者:

given ("foo/bar/") {
    when (-d) { ... }
    default { ... }
}

对我来说,尤其是第一个版本看起来比if-else构造或使用三元运算符更好,当依赖于我需要在两种情况下执行操作的测试结果时。

这让我很奇怪,除了简单的回归智能匹配以及避免过长的if-elsif-elsif -...-其他结构之外,还有什么看起来很整洁?

我有一种预感,给予/什么时候可以聪明而不失清晰,但我没有任何好的例子。

令我惊讶的一件事是,你可以嵌套构造以及:

given ($filename) {
        when (-e) {
                when (-f) {
                        when (-z) { say "Empty file" }
                        default { say "Nonempty file" }
                }
                when (-d) {
                        when (-o) { say "Directory owned by me"}
                        default { say "Directory owned by someone else" }
                }
                default { say "Special" }
        }
        default { say "No such file or directory" } }

2 个答案:

答案 0 :(得分:3)

recent answer到Zaid的问题Strategies to handle a file with multiple fixed formats中,我结束了一个穷人的yacc,其主循环搜索了第一场比赛的正则表达式数组:

while (<>) {
  given($_) {
    when (@{[ map $pattern{$_}, @expect ]}) {}
    default {
      die "$0: line $.: expected " . join("|" => @expect) . "; got\n$_";
    }
  }
}

在另一个问题中,David B wanted to match against multiple regexesmy answer uses smart matching隐式循环使用正则表达式:

#! /usr/bin/perl

use warnings;
use strict;

use feature 'switch';

my @patterns = (
  qr/foo/,
  qr/bar/,
  qr/baz/,
);

for (qw/ blurfl bar quux foo baz /) {
  print "$_: ";
  given ($_) {
    when (@patterns) {
      print "hit!\n";
    }
    default {
      print "miss.\n";
    }
  }
}

答案 1 :(得分:2)

不知道下面是否是一个整洁的用例,或者只是对Perl的语言血统的一小部分:)

# things todo (or should have done!) at this time of the day:

given (TheTime->of_day) {

    when ('morning') {
        breakfast();
        make_packed_lunch() if $_->is_work_day;
    }

    lunch() when 'afternoon';

    when ('evening') {
        goto_pub() if $_->is_friday;
        dinner();
    }

    default { say "Should be sleeping if its " . $_->{dt}->ymd }
}

如果您查看$_ “it”,那么它的效果特别好(恕我直言)。

以上工作由overloading given/when所依赖的智能匹配运算符完成。以下是编写TheTime类以使我的示例有效的方法:

{
    package TheTime;
    use DateTime;
    use overload '~~' => '_check_hour', fallback => 1;

    our %day_time = (
        morning   => [0..11],
        afternoon => [12..17],
        evening   => [18..23],
    );

    sub of_day {
        my $class = shift;
        bless {
            dt => DateTime->now,
        }, $class;
    }

    sub is_work_day { shift->{dt}->day_of_week ~~ [1..5] }
    sub is_friday   { shift->{dt}->day_of_week == 5      }

    sub _check_hour {
        my ($self, $greeting) = @_;
        $self->{dt}->hour ~~ $day_time{$greeting};
    } 
}

/ I3az /

PS。另请参阅我最近做的这篇博文:given/when – the Perl switch statement