Home > Raku > Coercive files

Coercive files

Many APIs have a routine or two that take a file as an argument. In Raku we can easily turn Str into IO::Path and subsequently into IO::Handle. As a module author it’s a polite move to provide MMD variants, so the user can supply what they like.

sub s($file is copy where { $_ ~~ Str|IO::Path|IO::Handle or fail(&?ROUTINE.name ~ ' likes Str, IO::Path and IO::Handle.') } ) {
    given $file {
        when Str { $file = .IO.open; }
        when IO::Path { $file = .open; }
        when IO::Handle { }
    }

    say ?$file;
}

This is boilerplate. Which in the kingdom of Raku is almost banned. Using the new coercion protocol, we can implement a role to happily save time ever after.

role Filish[*%mode] is IO::Handle {
    proto method COERCE($) {*}
    multi method COERCE(Str:D $s) {
        my $handle = self.new: :path($s.IO);
        $handle.open: |%mode
    }
    multi method COERCE(IO::Path:D $p) {
        my $handle = self.new: :path($p);
        $handle.open: |%mode
    }
    multi method COERCE(IO::Handle:D $h) {
        $h
    }
}

sub f(Filish[:w, :a, :!bin]() $handle) {
    $handle.put: "foo" xx 42;
    $handle.close;
}

f('/tmp/foo.txt');

With the coercing type constraint Filish[:w, :a, :!bin]() we basically say: “Give me something that represents a file, that I will open for writing in the appending fashion.”. I was not aware of the possibility to use a slurpy in the parameter list of a role (*@a works too). This seems to be an ENODOC. Since it makes my file easier I wont complain.

The new coercion protocol is very useful but got one flaw. It forces me to return the type that contains the COERCE-method. In a role that doesn’t make much sense and it forces me to juggle with IO::Handle. It took me 30 minutes to figure out how to successfully subclass it. There may be classes in modules that are even worse. Some programmers really like their private attributes. It would be nice to drop that restrictions on roles and/or if a return type is explicitly provided. With the current model, something easy is made hard.

Anyway, I got it working and might stick a module into the ecosystem, once I came up with a good name.

Categories: Raku
  1. December 27, 2020 at 03:00

    I strongly disagree with the statement about the coercion flaw. But to reason my disagreement a comment field isn’t the best place, so a published it as a post: https://vrurg.github.io/2020/12/26/Coercion-Return-Values

  1. December 28, 2020 at 19:51

Leave a comment