Perl6 制作一个可观察的计时器

Perl6 Making an observable timer

我正在尝试使用计时器 class 编写一个观察者模式,它会在给定的时间间隔调用其订阅者。一直在努力理解 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;
    }
}

Observer 角色只有一个包含订阅者的数组。当然,我应该制定一种方法来更新角色内的所有订阅者。

role Observable {
    has ActionListener @!action_listeners;

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

    method removeActionListener{
        @!action_listeners.pop;
    }
}

ActionListener 角色只有一个 actionPerformed 方法。 class ActionEvent 可能不是必需的,目前它只是一个空 class。

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;

订阅者 class 实现了 ActionListener 角色(有一个名为 actionPerformed 的方法)。

虽然这工作正常:订阅者的 actionPerformed 方法被调用,直到我调用计时器的停止方法。虽然没有适当的方法来删除给定的订阅者。另外我想知道是否有更好的方法 keep/break 从外部给定无限循环的承诺。

我基本上想知道我是否会错过 Perl6 中的内置功能?我是在重新发明轮子吗?

回答你的问题"Am I reinventing the wheel?"。有可能。

你实际上可以让当前的 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,那么 不是 去。如果您想创建观察者模式,这可能是最简洁的创建方式。

进一步回答重新发明轮子的问题:你应该看看 SupplySupplyObservable 的 Perl 6 术语,TapSubscription.

的 Perl 6 术语

为了获得定期调用订阅者的可观察对象,您可以使用 the interval class method of the Supply type。每当 Supply emit 的值和.tap call 是您可以用来关闭订阅的 Tap 对象。

These talk slides by Jonathan Worthington 如果您想了解更多关于耗材的信息,可能会很有趣。