Perl6 Создание наблюдаемого таймера - PullRequest
0 голосов
/ 28 июня 2018

Я пытаюсь написать шаблон наблюдателя, используя класс таймера, который вызывает своих подписчиков с заданным интервалом. Все время пытаясь понять концепцию обещаний в Perl6.

class Timer does Observable
{
    has Promise $!p;
    has Int $!interval;
    has Bool $!active = False;

    submethod BUILD(Int :$!interval) {}

    method start {
        $!p = Promise.start( {
            $!active = True;
            loop {
                sleep($!interval);
                @!action_listeners>>.actionPerformed(ActionEvent.new);
                if !$!active {$!p.keep}
            }
        });
    }

    method stop {
        $!active = False;
    }
}

Роль Обозреватель просто имеет массив с подписчиками. Конечно, я должен был создать метод обновления всех подписчиков в роли.

role Observable {
    has ActionListener @!action_listeners;

    method addActionListener(ActionListener $al){
        @!action_listeners.push($al);
    }

    method removeActionListener{
        @!action_listeners.pop;
    }
}

Роль ActionListener просто имеет метод actionPerformed. Класс ActionEvent может быть не обязательным, на данный момент это просто пустой класс.

role ActionListener
{
    method actionPerformed(ActionEvent $e) { ... }
}

Запуск из скрипта:

my Subscriber $s = Subscriber.new;
my Timer $t = Timer.new(interval => 1);

$t.start;
$t.addActionListener($s);
$t.addActionListener(Subscriber.new);

.... #doing stuff that lasts for a while
$t.stop;

Класс подписчика реализует роль ActionListener (имеет метод с именем actionPerformed).

Хотя это работает нормально: метод actionPerformed подписчиков вызывается до тех пор, пока я не вызову метод stop таймера. Пока нет правильного способа удалить данного подписчика. Также мне было интересно, есть ли лучший способ сохранить / нарушить обещание извне, учитывая, что код циклически повторяется.

Мне в основном интересно, не могу ли я упустить встроенные функции в Perl6? Я изобретаю колесо?

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Чтобы ответить на вопрос о переизобретении колеса еще дальше: вам следует взглянуть на Supply . Supply - это термин Perl 6 для Observable, а Tap - это термин Perl 6 для Subscription.

Чтобы получить наблюдаемое, которое вызывает абонентов через регулярные промежутки времени, вы можете использовать метод интервального класса типа снабжения . Вы должны вызвать .tap в результате вызова .interval, чтобы зарегистрировать блок кода, который будет выполняться всякий раз, когда значение Supply emit sa и результатом вызова .tap является объект Tap, который вы можете закрыть подписку с помощью.

Эти слайды для разговоров Джонатана Уортингтона могут быть интересны, если вы хотите узнать больше о припасах.

0 голосов
/ 28 июня 2018

Чтобы ответить на ваш вопрос «Изобретаю ли я колесо?». Возможно.

На самом деле вы можете попросить текущий ThreadPoolScheduler (он же $*SCHEDULER) запросить фрагмент кода, который будет выполняться с интервалом:

my $canceller = $*SCHEDULER.cue( { say $++ }, every => 0.2 );
sleep 2;
# 0 1 2 3 4 5 6 7 8 9
$canceller.cancel;
say "stopped";  # no numbers should be seen afterward
# stopped    
sleep 1;        # keep from exiting immediately

Это не включает никаких Promise с, поэтому, если ваша цель - узнать больше о Promise с, то это не путь. Если вы хотите создать шаблон наблюдателя, это может быть самый чистый способ его создания.

...