Home > Uncategorized > Keys are optional

Keys are optional

On my quest to a concurrent File::Find I found the need to have arguments (in this case as Bool) that are of a group of sorts and are mutual exclusive. Enums are very groupy, introduce easy to use names into the scope (directly or via is export) and should be easy to make mutual exclusive. The easy part was a bit naive because typed slurpy arguments are not supported (yet). If there is no easy way, there must be a hard way that is possible.

First let’s define two enums that serve as options to find.

package Find {
  enum Type (<File Dir Symlink>);
  enum Options (<Recursive Keep-going>);
}

Now we can have a where-clause that first checks if all members of a slurpy array are either of type Find::Type or Find::Options. Then we can check how many elements of Find::Options there are. Since there can be only one we complain about exclusiveness if there are to many.

+@options where {
  @options.all (elem) (Find::Type::.values (|) Find::Options::.values)
  && (+(@options.grep: * ~~ Find::Type) <= 1 or die "can only check for one type at a time")
}

In the body of the routine we can use junctions and smart matching to check if options are present.

my Bool $recursive = any(@options) ~~ Find::Recursive;
my %tests = Find::File => {so .f}, Find::Dir => {so .d}, Find::Symlink => {so .l};
@tests.append(%tests{@options.grep: * ~~ Find::Type});

The routine is then called with a list of flags at the end of it’s parameter list.

find(%*ENV<HOME>, include => {.extension eq 'txt'}, exclude => ['cfg', /.xml $/] , Find::File, Find::Recursive, Find::Keep-going);

The same would be possible to do with named arguments but I can’t see a way to do the exclusiveness in a where-clause. I like to have as much argument processing in the signature because it makes it easy to write documentation. Separate all arguments with a newline and then translate type constraints and where-clauses into plain English. Also, having enums as flags feels quite 6-ish and that’s what this blog (post) is about.

Categories: Uncategorized