Function-Parameters icon indicating copy to clipboard operation
Function-Parameters copied to clipboard

Possible to use class name as a type name?

Open mschout opened this issue 5 years ago • 4 comments

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) { ... }

mschout avatar Nov 02 '18 15:11 mschout

Does this work?

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

tobyink avatar Nov 02 '18 22:11 tobyink

It does. Thank you!

mschout avatar Nov 03 '18 15:11 mschout

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

vanHoesel avatar Feb 11 '19 00:02 vanHoesel

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.

tobyink avatar Feb 18 '19 00:02 tobyink

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.

mauke avatar Mar 31 '23 07:03 mauke

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";
}

tobyink avatar Mar 31 '23 07:03 tobyink