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
,那么 不是 去。如果您想创建观察者模式,这可能是最简洁的创建方式。
进一步回答重新发明轮子的问题:你应该看看 Supply。 Supply
是 Observable
的 Perl 6 术语,Tap
是 Subscription
.
的 Perl 6 术语
为了获得定期调用订阅者的可观察对象,您可以使用 the interval class method of the Supply type。每当 Supply
emit
的值和.tap
call 是您可以用来关闭订阅的 Tap
对象。
These talk slides by Jonathan Worthington 如果您想了解更多关于耗材的信息,可能会很有趣。
我正在尝试使用计时器 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
,那么 不是 去。如果您想创建观察者模式,这可能是最简洁的创建方式。
进一步回答重新发明轮子的问题:你应该看看 Supply。 Supply
是 Observable
的 Perl 6 术语,Tap
是 Subscription
.
为了获得定期调用订阅者的可观察对象,您可以使用 the interval class method of the Supply type。每当 Supply
emit
的值和.tap
call 是您可以用来关闭订阅的 Tap
对象。
These talk slides by Jonathan Worthington 如果您想了解更多关于耗材的信息,可能会很有趣。