Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create a callable variable to call a class method with arguments?

I'm trying to create a callable variable for a class method.

class Person {
    method walk(Str $direction) {
        say "Walking $direction";
    }
}

I can create a callable variable for the method 'walk' that works as expected.

my $person = Person.new;
my $callable = $person.^find_method('walk');
$person.$callable('up'); # OUTPUT: "Walking up"

Now I want to create a callable that will call method 'walk' with the parameter 'up'.

my $callable = $person.^find_method('walk').assuming('up');
$person.$callable(); 

    # Type check failed in binding to parameter '$direction'; expected Str but got Person (Person.new)
    #   in sub __PRIMED_ANON at EVAL_7 line 1
    #   in block <unit> at <unknown file> line 1

$person.$callable (without the parentheses) gives the same error

I tried calling it 'directly', but got a different error.

$person.^find_method('walk')('up')
    # Too few positionals passed; expected 2 arguments but got 1
    #   in method walk at <unknown file> line 2
    #   in block <unit> at <unknown file> line 1

Is this possible?

like image 460
Jim Bollinger Avatar asked Jun 25 '26 00:06

Jim Bollinger


1 Answers

Yes, this is possible. The missing piece is that methods implicitly receive their invocant as their first positional parameter (that is, the signature of Person's walk method is really method walk(Person: Str $direction)) and receive self as their first positional argument.

This means that you need to use assuming to supply the second positional argument instead of the first. Here's how that'd look:

class Person {
    method walk(Str $direction) {
        say "Walking $direction";
    }
}
my $person = Person.new;
my $callable = $person.^find_method('walk').assuming(*, 'up');
$person.$callable();  # # OUTPUT: "Walking up"

As another option, instead of using * for the first positional parameter, you could use $person; if you did that, $callable() would return "Walking up" without needing to be invoked on a Person.

like image 132
codesections Avatar answered Jun 27 '26 03:06

codesections



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!