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

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


7

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?

1 Answer
1


5

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.



Leave a Reply

Your email address will not be published. Required fields are marked *