Почему метод unwrap в Perl 6 является методом Routine?

Есть метод unwrap, но мне кажется, что я должен его использовать не так, как следует. Похоже, это должна быть либо отдельная процедура, либо метод в другом классе. Что мне не хватает?

Похоже, что ему все равно, что его вызывает, пока он получает правильную Routine::WrapHandle штуку в качестве аргумента. В этом примере я wrap выполняю подпрограмму и возвращаю WrapHandle:

sub add-two-numbers ( $n, $m ) { $n + $m }

sub do-some-stuff ( $n, $m, $o ) {
    add-two-numbers(  $n max $m, $m max $o );
    }

put do-some-stuff( 5, 10, 15 );

# now I want to look into do-some-stuff to see what it's
# passing
my $wraphandle = &add-two-numbers.wrap: {
    say "Arguments were (@_[])";
    callwith( |@_ );
    }

put do-some-stuff( 5, 10, 15 );

Затем я могу создать другую и не связанную процедуру и вызвать для нее unwrap:

my &routine = sub { 1 };
&routine.unwrap( $wraphandle );

put do-some-stuff( 5, 10, 15 );

Инвокант к unwrap кажется излишним. Действительно, я могу вызвать его как метод класса, и он все еще работает:

Routine.unwrap( $wraphandle );

Но, похоже, это должно быть либо рутиной (поскольку вызывающий не имеет значения):

unwrap( $wraphandle ); # doesn't exist

Или метод на Routine::WrapHandle, так как это источник поведения:

$wraphandle.unwrap;  # but, this method doesn't exist in that class

Итак, что мне не хватает в этом методе?


person brian d foy    schedule 04.05.2017    source источник


Ответы (1)


Предположительно, интерфейс был разработан одним способом (с подпрограммой, сохраняющей информацию и имеющей возможность удалять «пассивные» дескрипторы), но реализован другим (с дескриптором, уже сохраняющим всю необходимую информацию, чтобы он мог разворачиваться).

Что касается идеи, что unwrap, возможно, должен быть методом в дескрипторе: это действительно так, но метод называется restore, который Routine.unwrap просто делегирует (см. core/Routine.pm:110..113):

method unwrap($handle) {
    $handle.can('restore') && $handle.restore() ||
        X::Routine::Unwrap.new.throw
}

Если вам нужна полная история, помимо core/Routine.pm также есть Perl6::Metamodel::WrapDispatcher, определенный в Perl6/Metamodel/Dispatchers .nqp. Из того, что я вижу, конечно, должно быть возможно реализовать первоначальный дизайн, о котором я догадывался, но для этого нужен кто-то, кто достаточно серьезно относится к проблеме, чтобы действительно это сделать...

person Christoph    schedule 05.05.2017
comment
В документации по упаковке упоминалось, что WrapHandle является приватным, поэтому я не пошел по этому пути. На самом деле он возвращает Routine::WrapHandle, так что это тоже нужно исправить. - person brian d foy; 05.05.2017