Search code examples
perloopmoose

How can I get hold of all the arguments passed to a method with MooseX::Method::Signatures?


If I use MooseX::Method::Signatures, and I want to pass all the arguments onto a second method, I have to explicitly list them again:

method foo (Str :$bar!, Int: :$baz!) {
    ...
    return $self->_foo2(bar => $bar, baz => $baz);
}

It would be nice if I could do something like:

method foo (Str :$bar!, Int: :$baz!) {
    ...
    return $self->_foo2(%args);
}

This documentation for Method::Signatures suggests I can use @_ but that drops the named parameter keys.


Solution

  • Having done a little testing, it seems like MooseX::Method::Signatures is the "odd one out" of the major implementations of method signatures. All the others allow you to use @_ as expected; MXMS does not.

    use strict;
    use warnings;
    use Test::More 0.96;
    
    {
      package MyBase;
      sub new { bless {}, shift }
      sub _foo { \@_ }
    }
    
    {
      package UseKavorka;
      use Kavorka;
      use parent -norequire => qw(MyBase);
    
      method foo (Str :$bar!, Int :$baz!) {
        $self->_foo(@_);
      }
    }
    
    {
      package UseMS;
      use Method::Signatures;
      use parent -norequire => qw(MyBase);
    
      method foo (Str :$bar!, Int :$baz!) {
        $self->_foo(@_);
      }
    }
    
    {
      package UseMXMS;
      use Moose;
      use MooseX::Method::Signatures;
      extends qw(MyBase);
    
      method foo (Str :$bar!, Int :$baz!) {
        $self->_foo(@_);
      }
    }
    
    {
      package UseFP;
      use Function::Parameters;
      use parent -norequire => qw(MyBase);
    
      method foo (Str :$bar, Int :$baz) {
        $self->_foo(@_);
      }
    }
    
    for my $class (qw/ UseKavorka UseMS UseMXMS UseFP /)
    {
      my $obj = $class->new;
      is_deeply(
        $obj->foo(bar => "Hello world", baz => 42),
        [ $obj, bar => "Hello world", baz => 42 ],
        "\@_ worked fine in $class",
      );
    }
    
    done_testing;
    
    __END__
    ok 1 - @_ worked fine in UseKavorka
    ok 2 - @_ worked fine in UseMS
    not ok 3 - @_ worked fine in UseMXMS
    #   Failed test '@_ worked fine in UseMXMS'
    #   at foo.pl line 55.
    #     Structures begin differing at:
    #          $got->[1] = UseMXMS=HASH(0x92c0cc8)
    #     $expected->[1] = 'bar'
    ok 4 - @_ worked fine in UseFP
    1..4
    # Looks like you failed 1 test of 4.
    

    I'm biased because I wrote it, but my advice is to switch to Kavoka which gives you pretty much all the features of MooseX::Method::Signatures, but without the massive slow down.