I've worked out how to do it, by adding a custom dispatch:<.?> method:
use Test; class C { method foo { 42 } method can($meth-name) { my $meths = callsame; if !$meths && $meth-name eq 'bar' { $meths = [method { 69 }, ]; self.^add_method($meth-name, $meths[0]); } $meths; } method dispatch:<.?>(\name, |c) is raw { self.can(name) ?? self."{name}"(|c) !! Nil } method FALLBACK(\name, |c) { if self.can(name) { self."{name}"(|c); } else { die X::Method::NotFound.new( :method(name), :typename(self.^name) ); } } } for C { my $obj = .new; is $obj.foo, 42, 'static method - direct call'; is $obj.?foo, 42, 'static method - safe call'; is $obj.bar, 69, 'dynamic method - direct call'; is $obj.?bar, 69, 'dynamic method - safe call'; dies-ok {$obj.unknown}, 'direct call - unknown method dies'; lives-ok {$obj.?unknown}, 'safe call - unknown method lives'; } Based on some code I found in the core Rakudo Mu class. Slightly awkward, but at least working. On Tue, Oct 18, 2016 at 1:35 PM, David Warring <perl6-bugs-follo...@perl.org > wrote: > # New Ticket Created by David Warring > # Please include the string: [perl #129907] > # in the subject line of all future correspondence about this issue. > # <URL: https://rt.perl.org/Ticket/Display.html?id=129907 > > > > I'm adding a FALLBACK method to create method dynamically, the it receives > both '.' and '.?' invocations, and I can't distinguish between them. > > This then breaks $obj.unknown vs $obj.?unknown handling in class objects. > > Consider: > > use Test; > > class C { > method foo { 42 } > method FALLBACK($meth-name, |c) { > warn "can $meth-name"; > if $meth-name eq 'bar' { > self.^add_method($meth-name, method { 69 }); > self."$meth-name"(|c); > } > else { > warn "dunno if this is a safe method call or not"; > Nil; > } > } > } > > for C { > my $obj = .new; > is $obj.foo, 42, 'static method - direct call'; > is $obj.?foo, 42, 'static method - safe call'; > is $obj.bar, 69, 'dynamic method - direct call'; > is $obj.?bar, 69, 'dynamic method - safe call'; > todo "can't get both of these to pass!"; > dies-ok {$obj.unknown}, 'direct call - unknown method dies'; > lives-ok {$obj.?unknown}, 'safe call - unknown method lives'; > } > > I'm receiving both the safe and unsafe 'unknown' invocations, and can't > distinguish them. > > I also tried overriding the classes 'can' method: > > class C { > method foo { 42 } > method can($meth-name) { > my $meths = callsame; > if !$meths && $meth-name eq 'bar' { > $meths = [method { 69 }, ]; > self.^add_method($meth-name, $meths[0]); > } > $meths; > } > method FALLBACK($meth-name, |c) { > if self.can($meth-name) { > self."$meth-name"(|c); > } > else { > warn "dunno if this is a safe method call or not"; > Nil; > } > } > } > > But the FALLBACK is still needed, and still has the same problem. > > Any ideas? >