I need to pass some code from an external program into a class.
In a generic module I have (for simplicity reduced to silliness)
class A {
has &.hl;
submethod BUILD( :&!hl ) {}
}
Elsewhere in a program, I have
use A;
my &hl = -> $st {
my $p = shell "hl $st", :in,:out;
$p.out.slurp
};
my $statement = 'my $raku-variable = "Helloooo";'
my $first = &hl($statement);
my A $a .= new(:&hl);
my $second = $a.hl( $statement );
$first will be processed and will contain the expected results.
At $second, I will get a runtime error
Too many positionals passed; expected 1 argument but got 2
Clearly the routine in the class is being provided both the invocant and the parameter $s.
Rewriting the class to provide a custom accessor:
class A {
has &!hl;
submethod BUILD( :&!hl ) {}
method process-it( Str $s --> Str ) { &!hl( $s ) }
}
# elsewhere
my $second = $a.process-it( $statement );
Then both $first and $second run without error and will contain the same results.
When hl is accessed inside the class, no invocant is added, but if it is not declared as &.hl then it is not visible outside the class.
My question is therefore: Is there another way to create a public object code variable that does not automagically add the invocant as a variable to the code? Other than creating a separate accessor method.
Here is short bash script hl for illustration
#! /bin/bash
echo '<div class="statement">'$1'</div>'
Here is a full Raku program
use v6.c;
class A {
has &!highlighter; # also tried with has &highlighter
submethod BUILD( :&!highlighter ) {}
method process-it( Str $s --> Str ) {
&!highlighter( $s )
}
}
sub MAIN() {
my @strings = 'my $v = "Hello World";', 'my $w = $v.raku;';
my $proc;
my $proc-supply;
my &highlighter = -> $s {
my $p = shell "./hl '$s' ", :in,:out;
$p.out.slurp
}
for @strings {
say .&highlighter
}
my A $a .= new(:&highlighter);
for @strings { say $a.highlighter($_) }
# own accessor
for @strings { say $a.process-it($_) }
}