Как локализовать переменную в верхнем объеме в Perl?

Я натыкался на следующий шаблон несколько раз при разработке модулей Perl то использование AUTOLOAD или другая подпрограмма диспетчеризирует методы:

sub AUTOLOAD {
    my $self = $_[0];

    my $code = $self->figure_out_code_ref( $AUTOLOAD );

    goto &$code;
}

Это хорошо работает, и caller видит корректный объем.

Теперь то, что я хотел бы сделать, должно локально установить $_ равный $self во время выполнения &$code. Который был бы чем-то вроде этого:

sub AUTOLOAD {
    my $self = $_[0];

    my $code = $self->figure_out_code_ref( $AUTOLOAD );

    local *_ = \$self;

    # and now the question is how to call &$code

    # goto &$code;  # wont work since local scope changes will 
                    # be unrolled before the goto

    # &$code;  # will preserve the local, but caller will report an
               # additional stack frame  
}

Решения, которые включают обертывание caller не приемлемы из-за проблем зависимости и производительности. Таким образом, это, кажется, исключает вторую опцию.

Пятясь к первому, единственный способ предотвратить новое значение $_ от выхода из объема во время goto не должен был бы или локализовать изменение (не жизнеспособный вариант) или реализовать своего рода uplevel_local или goto_with_local.

Я играл вокруг со всеми видами вовлечения перестановок PadWalker, Sub::Uplevel, Scope::Upper, B::Hooks::EndOfScope и другие, но не смогли предложить надежное решение, которое моется $_ в нужное время, и не переносится caller.

Кто-либо нашел шаблон, который работает в этом случае?

(ТАК вопрос: Как я могу локализовать переменные Perl в другом стековом фрейме? связан, но сохранение caller не было требование, и в конечном счете ответ там должен был использовать другой подход, так, чтобы решение не было полезно в этом случае),

6
задан Community 23 May 2017 в 10:27
поделиться