perlsignatureintrospectionmoosemop

How to determine the arity of a ≥5.20 signatures method?


Problem shown below:

use 5.036; # signatures
use strictures;

package Foo {
    use Moose;
    sub quux($self) { ... }
}

package Big::Quux {
    use Moose::Role;
    sub quux($self, $another) { ... }
}

package Bar {
    use Moose;
    extends 'Foo';
    with 'Big::Quux';
}

package main {
    my $class = rand > .5 ? 'Foo' : 'Bar';
    say $class;
    $class->quux();
    # risks "Too few arguments for subroutine 'Big::Quux::quux' (got 1; expected 2)"
    $class->quux('something quuxable');
    # risks "Too many arguments for subroutine 'Foo::quux' (got 2; expected 1)"
}

Thus, I need to call quux with appropriate arguments depending on its signature/arity. The class is known at runtime, and $class->can('quux') handles inheritance correctly and provides the correct coderef. This introspection is straight-forward and painless in Kavorka, but how do I do that in plain Perl/Moose? I tried $class->meta->find_all_methods_by_name('quux'), but that seems to be a dead end.


Solution

  • You have two classes providing different interfaces. You need to use the interface that's appropriate for the class, so you write different code for the different classes.

    if ( $class->DOES( Big::Quux:: ) ) {
       $class->quux( 'something quuxable' );
    } else {
       $class->quux();
    }