NAME

Types::Sub - type constraints for subroutines and Sub::Meta

SYNOPSIS

use Test2::V0;
use Types::Sub -types;
use Types::Standard -types;

my $Sub = Sub[
    args    => [Int, Int],
    returns => Int
];

use Function::Parameters;
use Function::Return;

fun add(Int $a, Int $b) :Return(Int) {
    return $a + $b
}

ok $Sub->check(\&add);
ok !$Sub->check(sub {});

done_testing;

DESCRIPTION

Types::Sub is type library for subroutines and Sub::Meta. This library can be used with Moo/Moose/Mouse, etc.

Types

Sub[`a]

A value where Ref['CODE'] and check by Sub::Meta#is_relaxed_same_interface.

use Types::Sub -types;
use Types::Standard -types;
use Sub::Meta;

use Function::Parameters;
use Function::Return;

fun distance(Num :$lat, Num :$lng) :Return(Num) { }

#
# Sub[`a] is ...
#
my $Sub = Sub[
    subname => 'distance',
    args    => { '$lat' => Num, '$lng' => Num },
    returns => Num
];

ok $Sub->check(\&distance);

#
# almost equivalent to the following
#
my $submeta = Sub::Meta->new(
    subname => 'distance',
    args    => { '$lat' => Num, '$lng' => Num },
    returns => Num
);

my $meta = Sub::Meta::CreatorFunction::find_submeta(\&distance);
ok $submeta->is_relaxed_same_interface($meta);

done_testing;

If no argument is given, it matches Ref['CODE']. Sub[] == Ref['CODE']. This helps to keep writing simple when choosing whether or not to use stricter type checking depending on the environment.

use Devel::StrictMode;

has callback => (
    is  => 'ro',
    isa => STRICT ? Sub[
        args    => [Int],
        returns => [Int],
    ] : Sub[]
);

StrictSub[`a]

A value where Ref['CODE'] and check by Sub::Meta#is_strict_same_interface.

SubMeta[`a]

A value where checking by Sub::Meta#is_relaxed_same_interface.

StrictSubMeta[`a]

A value where checking by Sub::Meta#is_strict_same_interface.

EXAMPLES

Function::Parameters

use Function::Parameters;
use Types::Standard -types;
use Types::Sub -types;

my $Sub = Sub[
    args => [Int, Int],
];

fun add(Int $a, Int $b) { return $a + $b }

fun double(Int $a) { return $a * 2 }

ok $Sub->check(\&add);
ok !$Sub->check(\&double);

Sub::WrapInType

use Sub::WrapInType;
use Types::Standard -types;
use Types::Sub -types;

my $Sub = Sub[
    args    => [Int, Int],
    returns => Int,
];

ok $Sub->check(wrap_sub([Int,Int] => Int, sub {}));
ok !$Sub->check(wrap_sub([Int] => Int, sub {}));

Sub::WrapInType::Attribute

use Sub::WrapInType::Attribute;
use Types::Standard -types;
use Types::Sub -types;

my $Sub = Sub[
    args    => [Int, Int],
    returns => Int,
];

sub add :WrapSub([Int,Int] => Int) {
    my ($a, $b) = @_;
    return $a + $b
}

sub double :WrapSub([Int] => Int) {
    my $a = shift;
    return $a * 2
}

ok $Sub->check(\&add);
ok !$Sub->check(\&double);

Sub::Meta::Library

use Sub::Meta::Library;
use Types::Standard -types;
use Types::Sub -types;

my $Sub = Sub[
    args    => [Int, Int],
    returns => Int,
];

sub add {}
my $meta = Sub::Meta->new(
    args    => [Int, Int],
    returns => Int,
);
Sub::Meta::Library->register(\&add, $meta);

ok $Sub->check(\&add);

SEE ALSO

Sub::Meta::Type

LICENSE

Copyright (C) kfly8.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR

kfly8 <kfly@cpan.org>