Какие варианты аккуратного использования существуют для данного / когда? - PullRequest
10 голосов
/ 03 сентября 2010

В 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 -...- else структуры?

У меня есть предчувствие, что данное / когда позволяет быть умным, не теряя ясности, но у меня нет хороших примеров.

Одна вещь, которая удивила меня, это то, что вы можете вкладывать конструкцию также:

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 ]

3 голосов
/ 04 сентября 2010

В недавнем ответе на вопрос Заида Стратегии обработки файла с несколькими фиксированными форматами я закончил с yacc для бедного человека, основной цикл которого искал массив регулярных выражений дляпервое совпадение:

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

В другом вопросе Дэвид Б хотел сопоставить с несколькими регулярными выражениями , а в моем ответе используется интеллектуальное сопоставление для неявного зацикливания регулярных выражений:

#! /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";
    }
  }
}
2 голосов
/ 13 сентября 2010

Не знаю, является ли ниже аккуратный вариант использования или просто верхушка лингвистической линии 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 }
}

И если вы просматриваете $_ имеет "это" , то это работает особенно хорошо (ИМХО).

Вышеуказанное работает при перегрузке оператора интеллектуального сопоставления, на который 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. Также смотрите этот пост в блоге, который я недавно написал: данный / когда - оператор переключения Perl

...