I have a class that java would call a "bean". I would like to be able to merge in values for attributes in stages but also check that anything merged matches the submethod BUILD signature:
class A {
has Int $.a;
has Str $.b;
submethod BUILD ( Int :$!a, Str :$!b ) { }
my Signature $sig = ( A.^methods.grep: { .name eq 'BUILD' } )[0].signature;
method fill-in ( *%args ) {
say 'filling-in';
my @args = %args.pairs;
@args.unshift: self;
say 'after unshift';
self.raku.say;
my Capture $arg-capture = @args.Capture;
say 'after Capture';
self.raku.say;
unless $arg-capture ~~ $sig {
warn '(warning)';
return;
}
my Str $name;
my %merged;
say 'after check';
self.raku.say;
for self.^attributes -> Attribute $a {
$name = $a.name.substr: 2, *;
%merged{ $name } = ( $a.get_value: self ) // %args{ $name } // $a.type;
}
self.BUILD: |%merged.Capture;
}
}
my A $a = A.new: b => 'init';
$a.fill-in: a => 1;
outputs
filling in
after unshift
A.new(a => Int, b => "init")
after Capture
A.new(a => Int, b => "init")
after check
A.new(a => 1, b => Str)
if the @args.unshift: self is changed to @args.unshift: A, then after Capture it dies with
Cannot look up attributes in a A type object...
I realize I don't need to do this since the fill-in code only considers attributes that exist in the class but wonder if clearing the values from the Capture invocant when checking whether the signature will accept it is the expected behavior?
unshifting a throw-away instance ( @args.unshift: A.new ) works around the behavior.