Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

raku

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?

like image 579
brian d foy Avatar asked May 04 '17 22:05

brian d foy


1 Answers

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...

like image 76
Christoph Avatar answered Oct 01 '22 06:10

Christoph