Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syntax of the method of an instantiated object: can't seem to get it right

I want to get a pointer to an object method, for instance for this class

class Foo { 
    has $thing = "baz"; 
    method bar() { say $thing }
}; 

sub quux( Callable $flimflam ) { 
    $flimflam() 
}; 
my $foo = Foo.new;

I want to grab of the $foo.bar method pointer to pas it to quux. However, this

quux(&($foo.bar))

fails with Type check failed in binding to parameter '$flimflam'; expected Callable but got Bool (Bool::True)␤ in sub quux

This does not work either

quux($foo.bar)

maybe because it takes no parameters; however, if we change the definition of bar to:

 method bar($some ) { say $some ~ $thing }

Then the error for the call above becomes Too few positionals passed; expected 2 arguments but got 1␤ in method bar, the error creeps up to bar itself, which means the object itself does not get in.

I have checked out this answer, but it's for a class method (new) and it involves using the meta-object protocol. Would there be a simpler way of doing that?

like image 727
jjmerelo Avatar asked Jul 22 '18 09:07

jjmerelo


1 Answers

You can get the "static" method with .^lookup (the ^ indicates that it's a call on the meta object).

That method is not bound to the invocant $foo in any way, so you have to call it as

class Foo { 
    has $thing = "baz"; 
    method bar() { say $thing }
}; 

sub quux( Callable $flimflam ) { 
    $flimflam() 
}; 
my $foo = Foo.new;

my $method_bar = $foo.^lookup('bar');
$method_bar($foo);

You can use a closure to bind the method to the invocant:

my $bound_method = -> |c { $method_bar($foo, |c) }

Perl 6 also has a shortcut built in for that:

my $bound_method = $method_bar.assuming($foo);

But you can see that you could abbreviate the whole thing as

my $callback = { $foo.bar() }

or if the method potentially takes more arguments

my $callback = -> |c { $foo.bar(|c) }
like image 74
moritz Avatar answered Oct 01 '22 05:10

moritz