Home > Raku > Matching nothing

Matching nothing

I requested and foolishly offered help with a Discord log bot to lizmat. While doing so I stumbled upon a neat use for none().

sub discord-log-stream(Mu:D :$channels is copy = %*ENV<DISCORD-CHANNELS> // none()) {
    $channels = $channels.split('#', :skip-empty).any;

    # ...

    start react {
        whenever $discord.messages -> $message {
            next unless $channels ~~ $message.channel.name;

            $result.emit: [ ‚#‘ ~ $message.channel.name, $message.author.&{ .username ~ ‚#‘ ~ .discriminator }, $message.content ];
        }
    }
}

If no channel list is given, the bot shall log all channels. Instead of special casing, I use an empty none-Junction as a default value. With channels to include, $channel contains an any-Junction of Str. Matching a single Str with ~~ will return True if the string is also in the any-Junction. Any test against none() will return True. So my default value will always test True. This is a little bit like matching against the inverse of the empty set.

As it happens none() is quite resilient. It survives both .split and .any. Being an instance of Junction makes it defined. That is helpful because it allows the :D-type smiley and as such guards against undefined values.

Given that none() is everything I would not wonder if one who masters Raku goes straight to निर्वाण.

Update:

Since none() is anything but obvious, adding a constant with a speaking name adds clarity.

constant all-channels := none();

sub discord-log-stream(Mu:D :$channels is copy = %*ENV<DISCORD-CHANNELS> // all-channels) {
    # ...
}

Categories: Raku
  1. No comments yet.
  1. June 22, 2021 at 13:53

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: