Home > Raku > A hard simple thing

A hard simple thing

Bugs that originate in reliable subsystems are hard to spot because we don’t expect them to fail. A filesystem path usually just works. This has bit me a few times before. While renovating my backup script I found that I provide quite a few status and debug messages that basically call .gist on an IO::Path instance. Since one might want to use a hypothetical path, Raku can’t complain on non-existing paths until they are used. Further, it can be quite useful to know that a path is a symlink. Bash and friends help here with colour coding. Since I have plenty of say-calls, it would be nice to change them all in one go. So wraping it is!

my &RED = sub (*@s) { "\e[31m{@s.join('')}\e[0m" }
my &GREEN = sub (*@s) { "\e[32m{@s.join('')}\e[0m" }
my &CYAN = sub (*@s) { "\e[36m{@s.join('')}\e[0m" }

my &io-path-gist = IO::Path.^can('gist')[0];

&io-path-gist = &io-path-gist.wrap(my method gist (Mu: --> Str ) {
    nextsame unless self ~~ IO::Path;

    my $s = self.Str;
    $s = self.e && self.r ?? $s !! RED($s);
    $s = self.l ?? CYAN($s) !! $s;
    $s = self.x && !self.d ?? GREEN($s) !! $s;
    $s = self.d ?? $s ~ ‚/‘ !! $s;

}).&{ -> { .restore } };

We get a handle on the proto of .gist because .wrap never operates on multi candidates (this might change, see here). I’m using a method with Mu as the invocant for clarity. A sub with a single positional would do as well. Since the wrapper is called by the proto, we need to redispatch on anything but IO::Path. The returned WrapHandle isn’t really useful and neither is the unwrapped handle to .gist. By storing a closure we can restore the default by calling io-path-gist(). The rest is some colouring and adding a / to mark directories. I like to put a path into fancy quotes to make it easy to spot leading and trailing white spaces.

Declaring class-methods and calling them is a hard thing that is easy because the implementer was sufficiently tormented. Getting hold of methods at runtime is a simple thing that is hard. Huffmanizing applies. We call methods much more often then wrapping them. Sometimes it is good to break a design principle.

Categories: Raku
  1. p6steve
    January 8, 2021 at 21:15

    Hi @gfldex, please can you elaborate a few things (I can’t quite follow) – (i) why the ‘my’ for method in signature? (ii) what is the invocant of this method? (iii) why go “($s)” at the end – are you returning a list? Thanks in anticipation !

    • January 9, 2021 at 00:31

      i) I’m wrapping a method so I use a method as a wrapper.
      ii) The invocant can be any type that inherits .gist from Mu because the wrapper is wrapping the proto. The proto for .gist is defined in Mu.
      iii) It’s actually a string with fancy quotes sandwiching the path.

  1. January 11, 2021 at 21:05

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: