Typed filters
The Discord Raku bot is now also an IRC -> Discord bridge. To handle the streams of messages I use a react
-block with a few whenever
s. I would like to handle filtering of debug output from API::Discord in there as well, without disrupting something simple like printing to the terminal.
In my last post I showed how I can control the behaviour of a module with the use statement. The next step is to divert writes to $*ERR
to a Supply
.
my $active = False;
sub debug-print(|c) {
$*ERR.print: |c if $active;
}
sub debug-print-supply(Supply $in? --> Supply:D) {
my $result = $in // Supplier::Preserving.new;
&debug-print.wrap(-> |c {
$result.emit: |c
});
$result.Supply
}
multi sub EXPORT('FROM-MODULE') {
%(
'&debug-print' => &debug-print,
)
}
multi sub EXPORT() {
$active = True;
%(
'&debug-print' => &debug-print-supply,
)
}
As long as the user of the module doesn’t call debug-print
, we have the simple case of writing to $*ERR
. When debug-print
is called, we divert the stream into a Supply
. If no Supply
is supplied, we create one. To be able to filter output a role is created in API::Discord::Debug
.
role LogEventType is export {}
This role is indeed empty and so are the roles that are created to provide filters.
unit module Testmodule;
use API::Discord::Debug <FROM-MODULE>;
role HEARTBEAT does LogEventType is export {}
role PING does HEARTBEAT does LogEventType is export {}
start loop {
sleep ¼;
debug-print("ping" but PING);
debug-print("pong" but PONG) unless 10.rand < 2;
}
So we create a Str
and mixin a role, what is a type object we can check against.
use API::Discord::Debug;
use Testmodule;
react {
my $pings = 0;
whenever debug-say().merge(debug-print()) {
when PING { $pings++; }
when PONG { $pings--; }
default { .note }
}
whenever Supply.interval(5) {
say „$pings heartbeats are lost“ if $pings > 1;
}
}
Mixing in an empty role wont upset any unsuspecting bystander and type checks compose well. Here I use them with when
/default
, a multi dispatch would work as well. Introspection can be done with .WHAT.say
.
On CPAN we can find many “complete” modules that kill a specific problem once and for all. For many of those, there tends to be another module suffixed with ::Simple
. Simple stuff should be simple because we can’t buy any more days in this life. We also don’t take anything with us. I hope I can leave something simple behind instead.
-
June 29, 2021 at 13:062021.26 R3 – Rakudo Weekly News