Почему я не могу вызвать мета-методы в Routine::WrapHandle?
Это постоянный вопрос из моего предыдущего. Почему метод развёртывания в Perl 6 является рутинным методом?, но в основном не связано.
wrap
задокументировано, что метод возвращает "экземпляр частного класса с именем WrapHandle. Кроме того, что он странен для утечки частного класса, это не название возвращаемой вещи. Класс на самом деле 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
Но вот вопрос. Я хотел позвонить .^methods
на Routine::WrapHandle
, Это не работает:
> Routine::WrapHandle.^methods
Could not find symbol '&WrapHandle'
in block <unit> at <unknown file> line 1
Это то же самое, что пытаться использовать неопределенное имя класса:
> Foo::Baz.^methods
Could not find symbol '&Baz'
in block <unit> at <unknown file> line 1
Я могу вызвать мета-методы на экземпляре, хотя:
> $wrap-handle.^methods
(restore)
> $wrap-handle.^name
Routine::WrapHandle
Что там происходит?
1 ответ
Определение Routine::WrapHandle
выглядит примерно так:
my class Routine {
method wrap(&wrapper) {
my class WrapHandle { ... }
...
}
}
Мы можем игнорировать окружающий метод; важно то, что мы имеем дело с лексическим внутренним классом, определенным внутри внешнего класса. Упрощая еще немного, мы приходим к следующей схеме:
package Foo {
my class Bar {}
say Bar.^name; #=> Foo::Bar
}
say try Foo::Bar; #=> Nil
Полное имя внутреннего класса будет включать имя включающего пакета, но из-за явного my
(вместо неявного our
), класс не будет установлен как переменная пакета, и поиск в области видимости файла завершится неудачно.