mauke / Function-Parameters

Function::Parameters - define functions and methods with parameter lists ("subroutine signatures")
https://metacpan.org/pod/Function::Parameters
18 stars 19 forks source link

Possible to use class name as a type name? #36

Closed mschout closed 1 year ago

mschout commented 5 years ago

In porting over a codebase from Method::Signatures, I am dealing with a lot of methods that were using class names in the parameter lists. For example:

use Function::Parameters;
use URI;
use Types::Standard qw(ArrayRef);
method foo(URI $uri) { ... }   # Undefined type name error
method foobar(ArrayRef[URI] $uris) { ... }  # missing type name after '[' error

This seems to not work with Function::Parameters, or, I have missed the way to get these working. Using Types::Standard I tried things such as:

use Types::Standard qw(InstanceOf ArrayRef);
method foo1(InstanceOf[URI] $uri) { ... }    # Undefined type name URI error
method foo2(InstanceOf['URI'] $uri) { ... }  # missing type name after '[' error
method foo3(ArrayRef[ InstanceOf[URI] ] $uris) { ... }    # Undefined type name URI error
method foo4(ArrayRef[ InstanceOf['URI'] ] $uris) { ... }  # missing type name after '[' error

So either I am missing how to get this to work, or, I need to drop the class type constraints altogether and just use something like:

method foo1($uri) { ... }
method foo2(ArrayRef $uris) { ... }
tobyink commented 5 years ago

Does this work?

method foo2((InstanceOf['URI']) $uri) { ... }
mschout commented 5 years ago

It does. Thank you!

vanHoesel commented 5 years ago

@tobyink ... can you please explain why method foo( InstanceOf['URI'] $uri) { ... } is not working?

tobyink commented 5 years ago

Because you left out the parentheses around the type name.

method foo((InstanceOf['URI']) $uri) { ... }

See the Function::Parameters documentation for what exactly those do.

mauke commented 1 year ago

In addition to what @tobyink said, you can also define ad-hoc type constants:

use constant {
    T_URI => InstanceOf['URI'],
};
method foo(T_URI $uri, ArrayOf[T_URI] $uris) { ... }

Or for maximum DWIMery, write a custom type reifier that turns undefined type names (which are normally looked up as subroutines in the current package) into InstanceOf constraints.

tobyink commented 1 year ago

If you have a recent version of Type::Tiny installed, the following should also work:

use Function::Parameters;
use Type::Tiny::Class v2.0 qw( URI HTTP::Tiny );

method get_uri ( URI $uri, HTTPTiny $ua ) {
  my $response = $ua->get( $uri );
  if ( $response->{success} ) {
    return $response->{content};
  }
  die "response failed";
}