Why is Perl 6's unwrap method a method of Routine?

raku

Solution

At a guess, the interface was designed one way (with the routine keeping the information and being able to remove 'passive' handles), but implemented another (with the handle already keeping all required information so it can unwrap itself).

As to the notion that `unwrap` should perhaps be a method on the handle: It actually is, but the method is called `restore`, which `Routine.unwrap` merely delegates to (cf core/Routine.pm:110..113):

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

If you want the full story, besides core/Routine.pm, there's also `Perl6::Metamodel::WrapDispatcher` defined in Perl6/Metamodel/Dispatchers.nqp. From what I can see, it certainly should be possible to implement the original design I conjectured, but it would need someone feeling strongly enough about the issue to actually do it...

Problem

There's an `unwrap` method, but the way it seems I'm supposed to use it isn't the way it should be used. It seems like it should either be a standalone routine or a method in a different class. What am I missing? It appears that it doesn't care what its invocant is as long as it gets the right `Routine::WrapHandle` thingy as an argument. In this example, I `wrap` a subroutine and get back a `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 ); ``` Then, I can create a different and unrelated routine and call `unwrap` on that: ``` my &routine = sub { 1 }; &routine.unwrap( $wraphandle ); put do-some-stuff( 5, 10, 15 ); ``` The invocant to `unwrap` seems superfluous. Indeed, I can call it as a class method and it still works: ``` Routine.unwrap( $wraphandle ); ``` But, it seems this should either be a routine (since the invocant doesn't matter): ``` unwrap( $wraphandle ); # doesn't exist ``` Or a method on `Routine::WrapHandle` since that's the source of the behavior: ``` $wraphandle.unwrap; # but, this method doesn't exist in that class ``` So, what am I missing about this method?

Original source