This is a continuing question from my previous one Why is Perl 6's unwrap method a method of Routine?, but mostly unrelated.
The wrap
method is documented to return "an instance of a private class called WrapHandle. Besides that being odd for leaking a class that's private, it's not actually the name of the thing that comes back. The class is actually Routine::WrapHandle
:
$ perl6
> sub f() { say 'f was called' }
sub f () { #`(Sub|140397740886648) ... }
> my $wrap-handle = &f.wrap({ say 'before'; callsame; say 'after' });
Routine::WrapHandle.new
But here's the question. I wanted to call .^methods
on Routine::WrapHandle
. That doesn't work:
> Routine::WrapHandle.^methods
Could not find symbol '&WrapHandle'
in block <unit> at <unknown file> line 1
This is the same as trying it on an undefined class name:
> Foo::Baz.^methods
Could not find symbol '&Baz'
in block <unit> at <unknown file> line 1
I can call meta methods on the instance though:
> $wrap-handle.^methods
(restore)
> $wrap-handle.^name
Routine::WrapHandle
What's going on there?
The definition of Routine::WrapHandle
looks something like this:
my class Routine {
method wrap(&wrapper) {
my class WrapHandle { ... }
...
}
}
We can ignore the surrounding method; the important bit is that we're dealing with a lexical inner class defined within an outer class. Simplifying some more, we arrive at the following pattern:
package Foo {
my class Bar {}
say Bar.^name; #=> Foo::Bar
}
say try Foo::Bar; #=> Nil
The fully qualified name of the inner class will include the name of the enclosing package, but due to the explicit my
(instead of the implicit our
), the class will not be installed as a package variable and the lookup at file scope fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With