Coercing coercion
Task 1 of PWC #216 is a Set
-operation.
for [('abc', 'abcd', 'bcd'), 'AB1 2CD'; ('job', 'james', 'bjorg'), '007 JB'; ('crack', 'road', 'rac'), 'C7 RA2'] -> [@words, $reg] {
say @words.grep($reg.lc.comb.grep(/<alpha>/) ⊆ *.comb);
}
The transformation of $reg
is a bit unwieldy. I could pull it out and transform it before I use it but then I would have to use is rw
. That ain’t neat. What if I could write a type that does the transformation for me? The answer is mildly insane.
role Trans[::From, ::To, &c] {
has To $.value;
method COERCE(From:D $old) {
my \instance = self.new(:value($old.&c));
my \table = instance.^method_table;
table{To.^name} = my method ::To(--> To) { $!value }
instance.^compose;
instance
}
}
constant ToSet = Trans[Str, Set, { .lc.comb.grep(/<alpha>/).Set }];
for [('abc', 'abcd', 'bcd'), 'AB1 2CD'; ('job', 'james', 'bjorg'), '007 JB'; ('crack', 'road', 'rac'), 'C7 RA2'] -> [@words, ToSet() $reg] {
say @words.grep($reg ⊆ *.comb);
}
I create a parametric role that is told how to transform a Str
to a Set
with a Block
and use that as a coercion-type. Things get tricky inside method COERCE
because I have to return the role or the coercion-protocol will throw X::Coerce::Impossible
. As a result I need to add a method called Set
to the parametrised role. Raku doesn’t have the syntax to specify an indirection for method-names (for definitions, calling them can be done with ."$foo"
). Hence the use of the MOP. Also, .^add_method
doesn’t take a :local
-adverb and thus refuses to overload methods provided by Mu
and Any
. Overwriting the name in the method table is a gnarly hack but works fine — as hacks do.
And so I got myself a way to run code at bind-time in signatures that changes arguments to what I need. I’m not sure what this could be useful for but will keep it in my toolbox nonetheless.
EVAL sadly doesn’t work, because quotes can’t form a closure over a code-object. I believe untangling this would be a nice test for RakuAST-macros and would improve readability for this example quite a bit. In fact, I wouldn’t need a parametric role but could craft a simple class.
-
May 15, 2023 at 17:382023.20 SO Survey – Rakudo Weekly News