How do I take a reference to new?
The error message is indeed confusing.
The :with
parameter expects a Callable. Card.new
is not a Callable. If you write it as :with( { Card.new($^number, $^suit) } )
, it appears to work.
Note that I did not use $^value, $^suit
, because they order differently alphabetically, so would produce the values in the wrong order. See The ^ twigil for more information on that syntax.
The error is LTA, this makes it a little bit better.
To get back to your question: you can find the code object that corresponds to Card.new
with ^find_method
. However, that will not work, as Card.new
actually expects 3 arguments: the invocant (aka self
), $value
and $suit
. Whereas the cross
function will only pass the value and the suit.
The title of your question is “How do I take a reference to new?”, but that is not really what you want to do.
Raku being Raku, you can actually get a reference to new
.
my $ref = Card.^lookup('new');
You can't use it like you want to though.
$ref(2,'Clubs'); # ERROR
The problem is that methods take a class or instance as the first argument.
$ref(Card, 2,'Clubs');
You could use .assuming
to add it in.
$ref .= assuming(Card);
$ref(2,'Clubs');
But that isn't really any better than creating a block lambda
$ref = { Card.new( |@_ ) }
$ref(2,'Clubs');
All of these work:
cross( @values, @suits ) :with({Card.new(|@_)}) # adverb outside
cross( @values, @suits, :with({Card.new(|@_)}) ) # inside at end
cross( :with({Card.new(|@_)}), @values, @suits ) # inside at beginning
@values X[&( {Card.new(|@_)} )] @suits # cross meta-op with fake infix op
do {
sub new-card ($value,$suit) { Card.new(:$value,:$suit) }
@values X[&new-card] @suits
}
do {
sub with ($value,$suit) { Card.new(:$value,:$suit) }
cross(@values,@suits):&with
}