Aion

 view release on metacpan or  search on metacpan

lib/Aion/Types.pm  view on Meta::CPAN

		$awhere? (a_test => $awhere): (),
		$message? (message => $message): (),
	);
	
	if($is_maybe_arg) {
		$type->make_maybe_arg($pkg)
	} elsif($is_arg || @init) {
		$type->make_arg($pkg, $is_arg)
	} else {
		$type->make($pkg)
	}
}
}

sub as(@) { (as => @_) }
sub init_where(&@) { (init_where => @_) }
sub where(&@) { (where => @_) }
sub awhere(&@) { (awhere => @_) }
sub message(&@) { (message => @_) }

sub SELF() { $Aion::Type::SELF }
sub ARGS() {
	return $Aion::Type::SELF->{is_param_args} if $Aion::Type::SELF->{is_param_args};
	wantarray? @{$Aion::Type::SELF->{args}}: $Aion::Type::SELF->{args}
}
sub A() { $Aion::Type::SELF->{args}[0] }
sub B() { $Aion::Type::SELF->{args}[1] }
sub C() { $Aion::Type::SELF->{args}[2] }
sub D() { $Aion::Type::SELF->{args}[3] }

sub M() :lvalue { $Aion::Type::SELF->{M} }
sub N() :lvalue { $Aion::Type::SELF->{N} }

# Создание транслятора. У типа может быть сколько угодно трансляторов из других типов
# coerce Type, from OtherType, via {...}
sub coerce(@) {
	my ($type, %o) = @_;
	my ($from, $via) = delete @o{qw/from via/};

	die "coerce $type unused keys left: " . join ", ", keys %o if keys %o;
	die "coerce $type not Aion::Type!" unless UNIVERSAL::isa($type, "Aion::Type");
	die "coerce $type: from is'nt Aion::Type!" unless UNIVERSAL::isa($from, "Aion::Type");
	die "coerce $type: via is not subroutine!" unless ref $via eq "CODE";

	push @{$type->{coerce}}, [$from, $via];
	return;
}

sub from($) { (from => $_[0]) }
sub via(&) { (via => $_[0]) }

use constant DBL_MAX => do {
	my $ieee_dbl_max_str = '1.7976931348623157e+308';
	($ieee_dbl_max_str+0) =~ /inf/i? do {
		require Math::BigFloat;
		Math::BigFloat->new($ieee_dbl_max_str)
	}: $ieee_dbl_max_str+0
};

sub _8BITS() {
	undef *_8BITS;
	require Math::BigInt;
	my $_8bits = Math::BigInt->new(8);
	constant->import(_8BITS => $_8bits);
	$_8bits
}

BEGIN {

subtype "Any";
	subtype "Control", as &Any;
        subtype "Union[A, B...]", as &Control,
            where { my $val = $_; any { $_->include($val) } ARGS };
        subtype "Intersection[A, B...]", as &Control,
            where { my $val = $_; all { $_->include($val) } ARGS };
		subtype "Exclude[A]", as &Control,
			where { !A->test };
		subtype "Option[A]", as &Control,
			init_where { SELF->{is_option} = 1 }
			where { A->test };
		subtype "Wantarray[A, S]", as &Control,
			init_where { SELF->{is_wantarray} = 1 }
			where { ... };

	subtype "Item", as &Any;
		sub External($) {
			local $_ = $_[0][0];
			UNIVERSAL::isa($_, 'Aion::Type')? $_:
			defined($_) && ref $_ eq ""? Object([$_]): do {
				die "Not External[${\val_to_str($_)}]" unless reftype($_) eq "CODE" || overload::Method($_, '&{}');
				Aion::Type->new(
					name => 'External',
					as => &Item,
					args => $_[0],
					test => $_,
					UNIVERSAL::can($_, 'coerce')
						? (coerce => [[&Any, (sub { my ($ex) = @_; sub { $ex->coerce } })->($_)]])
						: (),
				)
			}
		}
		subtype "Bool", as &Item, where { ref $_ eq "" and /^(1|0|)\z/ };
		subtype "BoolLike", as &Item, where {
			return 1 if overload::Method($_, 'bool');
			my $m = overload::Method($_, '0+');
			Bool()->include($m ? $m->($_) : $_) };
		subtype "Enum[e...]", as &Item,
			init_where { M = +{ map {($_ => $_)} ARGS } }
			where { exists M->{$_} };
		subtype "Undef", as &Item, where { !defined $_ };
		subtype "Maybe[A]", as &Undef | A;
		subtype "Defined", as &Item, where { defined $_ };
			subtype "Value", as &Defined, where { "" eq ref $_ };
				subtype "Version", as &Value, where { "VSTRING" eq ref \$_ };
				subtype "Str", as &Value, where { "SCALAR" eq ref \$_ };
					subtype "Uni", as &Str,	where { utf8::is_utf8($_) || /[\x80-\xFF]/a };
					subtype "Bin", as &Str, where { !utf8::is_utf8($_) && !/[\x80-\xFF]/a };
					subtype "NonEmptyStr", as &Str,	where { /\S/ };
					subtype "StartsWith[start]", as &Str,
						init_where { M = qr/^${\ quotemeta A}/ },
						where { $_ =~ M };

lib/Aion/Types.pm  view on Meta::CPAN

	}
	
	"Hi, my dear!" ~~ BeginAndEnd["Hi,", "!"]; # -> 1
	"Hi my dear!" ~~ BeginAndEnd["Hi,", "!"];  # -> ""
	
	"" . BeginAndEnd["Hi,", "!"] # => BeginAndEnd['Hi,', '!']

=head2 N

Shorthand for C<< SELF-E<gt>{N} >>.

=head2 message ($code)

Used with C<subtype> to print an error message if the value excludes the type. C<$code> uses: C<SELF> - the current type, C<ARGS>, C<A>, C<B>, C<C>, C<D> - type arguments (if any) and a test value in C<$_>. It can be converted to a string using C<< S...

=head2 coerce ($type, from => $from, via => $via)

Adds a new cast (C<$via>) to C<$type> from C<$from> type.

	BEGIN {
		subtype Four => where {4 eq $_};
	}
	
	"4a" ~~ Four # -> ""
	
	Four->coerce("4a") # -> "4a"
	
	coerce Four, from Str, via { 0+$_ };
	
	Four->coerce("4a")	# -> 4
	
	coerce Four, from ArrayRef, via { scalar @$_ };
	
	Four->coerce([1,2,3])           # -> 3
	Four->coerce([1,2,3]) ~~ Four   # -> ""
	Four->coerce([1,2,3,4]) ~~ Four # -> 1

Can use parameters like:

	BEGIN {
		subtype 'Plus[acc]', as Num;
	}
	coerce &Plus, from Num, via { $_ + A };
	
	Plus([5])->coerce(4) # -> 9
	Plus([5]) >> 5 # -> 10
	1 >> Plus[5] # -> 6

C<coerce> throws exceptions:

	eval {coerce Int, via1 => 1}; $@  # ~> coerce Int unused keys left: via1
	eval {coerce "x"}; $@  # ~> coerce x not Aion::Type!
	eval {coerce Int}; $@  # ~> coerce Int: from is'nt Aion::Type!
	eval {coerce Int, from "x"}; $@  # ~> coerce Int: from is'nt Aion::Type!
	eval {coerce Int, from Num}; $@  # ~> coerce Int: via is not subroutine!
	eval {coerce Int, (from=>Num, via=>"x")}; $@  # ~> coerce Int: via is not subroutine!

Standard casts:

	# Str from Undef — empty string
	Str->coerce(undef) # -> ""
	
	# Int from Num — rounded integer
	Int->coerce(2.5)  # -> 3
	Int->coerce(-2.5) # -> -3
	
	# Bool from Any — 1 or ""
	Bool->coerce([]) # -> 1
	Bool->coerce(0)  # -> ""

=head2 from ($type)

Syntactic sugar for C<coerce>.

=head2 via ($code)

Syntactic sugar for C<coerce>.

=head1 ATTRIBUTES

=head2 :Isa (@signature)

Checks the signature of a subroutine: arguments and results.

	sub minint($$) : Isa(Int => Int => Int) {
		my ($x, $y) = @_;
		$x < $y? $x : $y
	}
	
	minint 6, 5; # -> 5
	eval {minint 5.5, 2}; $@ # ~> Arguments of method `minint` must have the type Tuple\[Int, Int\]\.
	
	sub half($) : Isa(Int => Int) {
		my ($x) = @_;
		$x / 2
	}
	
	half 4; # -> 2
	eval {half 5}; $@ # ~> Return of method `half` must have the type Int. The it is 2.5

=head1 TYPES

=head2 Any

The top level type in the hierarchy. Compares everything.

The bottom type can be obtained as C<~Any>.

=head2 Control

The top-level type in hierarchy constructors creates new types from any types.

=head2 Union[A, B...]

Union of several types. Similar to the C<$type1 | $type2>.

	33  ~~ Union[Int, Ref] # -> 1
	[]  ~~ Union[Int, Ref] # -> 1
	"a" ~~ Union[Int, Ref] # -> ""

=head2 Intersection[A, B...]

lib/Aion/Types.pm  view on Meta::CPAN

=head2 Option[A]

Additional keys in C<Dict>.

	{a=>55} ~~ Dict[a=>Int, b => Option[Int]]          # -> 1
	{a=>55, b=>31} ~~ Dict[a=>Int, b => Option[Int]]   # -> 1
	{a=>55, b=>31.5} ~~ Dict[a=>Int, b => Option[Int]] # -> ""

=head2 Wantarray[A, S]

If the routine returns different values in array and scalar contexts, then the C<Wantarray> type is used with type C<A> for the array context and type C<S> for the scalar context.

	sub arr : Isa(PositiveInt => Wantarray[ArrayRef[PositiveInt], PositiveInt]) {
		my ($n) = @_;
		wantarray? 1 .. $n: $n
	}
	
	my @array = arr(3);
	my $scalar = arr(3);
	
	\@array # --> [1,2,3]
	$scalar  # -> 3

=head2 Item

The top-level type in the hierarchy of scalar types.

=head2 External[type]

Sets C<type> to C<Aion::Type>.

=over

=item * If C<type> is C<Aion::Type>, then returns it unchanged.

=item * If C<type> is a string, then wraps it in C<Object>.

=item * If C<type> can be called, then wraps it in C<< Aion::Type-E<gt>new(test =E<gt> $type, ...) >>. And if it has a C<coerce> method, it will use it for transformations. Thanks to this, it is possible to use external types like C<Type::Tiny> in th...

=back

	External['Aion'] # -> Object['Aion']
	External[sub { /^x/ }] ~~ 'xyz' # -> 1
	
	package MyInt {
		use overload "&{}" => sub {
			sub { /^[+-]?[0-9]+$/ }
		};
		
		sub coerce { /\./? int($_): $_ }
	}
	
	my $myint = bless {}, 'MyInt';
	
	External([$myint]) ~~ '+123' # -> 1
	External([$myint])->coerce(10.1) # => 10
	External([$myint])->coerce('abc') # => abc

=head2 Bool

C<1> is true. C<0>, C<""> or C<undef> is false.

	1 ~~ Bool  # -> 1
	0 ~~ Bool  # -> 1
	undef ~~ Bool # -> 1
	"" ~~ Bool # -> 1
	
	2 ~~ Bool  # -> ""
	[] ~~ Bool # -> ""

=head2 Enum[A...]

Enumeration.

	3 ~~ Enum[1,2,3];            # -> 1
	"cat" ~~ Enum["cat", "dog"]; # -> 1
	4 ~~ Enum[1,2,3];            # -> ""
	
	Enum["cat"] <= Enum["cat", "dog"] # -> 1
	Enum["cat", "dog"] <= Enum["cat", "dog"] # -> 1
	
	Enum(["cat", "dog"])->disjoint(Enum[1]) # -> 1
	Enum(["cat", "dog"])->disjoint(Enum["ret", "cat"]) # -> ""
	
	Enum[1,2] <= Enum[1,2,3]          # -> 1
	Enum[1,2] <= Enum[2,3]            # -> ""
	Enum[1,2] == Enum[2,1]            # -> 1
	Enum[1,2] < Enum[1,2,3]           # -> 1
	Enum[1,2,3] > Enum[1,2]           # -> 1
	Enum[1,2] == (Enum[1] | Enum[2])  # -> 1

=head2 Maybe[A]

C<undef> or type in C<[]>.

	undef ~~ Maybe[Int] # -> 1
	4 ~~ Maybe[Int]     # -> 1
	"" ~~ Maybe[Int]    # -> ""

=head2 Undef

Only C<undef>.

	undef ~~ Undef # -> 1
	0 ~~ Undef     # -> ""

=head2 Defined

Everything except C<undef>.

	\0 ~~ Defined    # -> 1
	undef ~~ Defined # -> ""

=head2 Value

Defined values without references.

	3 ~~ Value  # -> 1
	\3 ~~ Value    # -> ""
	undef ~~ Value # -> ""

=head2 Len[from?, to]

Specifies a length value from C<from> or 0 to C<to>.

	"1234" ~~ Len[3]   # -> ""
	"123" ~~ Len[3]    # -> 1
	"12" ~~ Len[3]     # -> 1
	"" ~~ Len[1, 2]    # -> ""
	"1" ~~ Len[1, 2]   # -> 1
	"12" ~~ Len[1, 2]  # -> 1
	"123" ~~ Len[1, 2] # -> ""
	
	Len[3] <= Len[3] # -> 1
	Len[3] <= Len[4] # -> 1
	Len[3] <= Len[2] # -> ""

=head2 Version

Perl version.

	1.1.0 ~~ Version   # -> 1
	1.1.0.5 ~~ Version # -> 1
	v1.1.0 ~~ Version  # -> 1
	v1.1 ~~ Version    # -> 1
	v1 ~~ Version      # -> 1
	1.1 ~~ Version     # -> ""
	"1.1.0" ~~ Version # -> ""

=head2 Str

Strings, including numbers.

	1.1 ~~ Str   # -> 1
	"" ~~ Str    # -> 1
	1.1.0 ~~ Str # -> ""

=head2 Uni

Unicode strings with the utf8 flag or if decoding to utf8 occurs without errors.

	"↭" ~~ Uni # -> 1
	123 ~~ Uni # -> ""
	do {no utf8; "↭" ~~ Uni} # -> 1

=head2 Bin

Binary strings without the utf8 flag and octets with numbers less than 128.

	123 ~~ Bin # -> 1
	"z" ~~ Bin # -> 1
	"↭" ~~ Bin # -> ""
	do {no utf8; "↭" ~~ Bin }   # -> ""

=head2 StartsWith[begin]

The line starts with C<begin>.

	"Hi, world!" ~~ StartsWith["Hi,"]; # -> 1
	"Hi world!" ~~ StartsWith["Hi,"];  # -> ""

lib/Aion/Types.pm  view on Meta::CPAN


	\12    ~~ ValueRef                 # -> 1
	\12    ~~ ValueRef                 # -> 1
	\-1.2  ~~ ValueRef[Num]            # -> 1
	\\-1.2 ~~ ValueRef[ValueRef[Num]] # -> 1

=head2 ScalarRef`[A]

Reference to a scalar.

	\12   ~~ ScalarRef      # -> 1
	\\12  ~~ ScalarRef      # -> ""
	\-1.2 ~~ ScalarRef[Num] # -> 1

=head2 RefRef`[A]

Link to link.

	\12    ~~ RefRef                 # -> ""
	\\12   ~~ RefRef                 # -> 1
	\-1.2  ~~ RefRef[Num]            # -> ""
	\\-1.2 ~~ RefRef[ScalarRef[Num]] # -> 1

=head2 GlobRef

Link to global

	\*A::a ~~ GlobRef # -> 1
	*A::a ~~ GlobRef  # -> ""

=head2 FileHandle

File descriptor.

	\*A::a ~~ FileHandle         # -> ""
	\*STDIN ~~ FileHandle        # -> 1
	
	open my $fh, "<", "/dev/null";
	$fh ~~ FileHandle	         # -> 1
	close $fh;
	
	opendir my $dh, ".";
	$dh ~~ FileHandle	         # -> 1
	closedir $dh;
	
	use constant { PF_UNIX => 1, SOCK_STREAM => 1 };
	
	socket my $sock, PF_UNIX, SOCK_STREAM, 0;
	$sock ~~ FileHandle	         # -> 1
	close $sock;

=head2 ArrayRef`[A]

Array references.

	[] ~~ ArrayRef	# -> 1
	{} ~~ ArrayRef	# -> ""
	[] ~~ ArrayRef[Num]	# -> 1
	{} ~~ ArrayRef[Num]	# -> ''
	[1, 1.1] ~~ ArrayRef[Num]	# -> 1
	[1, undef] ~~ ArrayRef[Num]	# -> ""

=head2 Lim[from?, to]

Limits arrays from C<from> or 0 to C<to> elements.

	[] ~~ Lim[5]     # -> 1
	[1..5] ~~ Lim[5] # -> 1
	[1..6] ~~ Lim[5] # -> ""
	
	[1..5] ~~ Lim[1,5] # -> 1
	[1..6] ~~ Lim[1,5] # -> ""
	
	[1] ~~ Lim[1,5] # -> 1
	[] ~~ Lim[1,5]  # -> ""
	
	Lim[0, 10] <= Lim[0, 20]        # -> 1
	Lim[10, 'Inf'] <= Lim[0, 'Inf'] # -> 1
	
	Lim[3] <= Lim[5]          # -> 1
	Lim[3] <= Lim[2]          # -> ""
	Lim[2,5] < Lim[1,6]       # -> 1
	Lim[2,5] == Lim[2,5]      # -> 1

=head2 HashRef`[H]

Links to hashes.

	{} ~~ HashRef # -> 1
	\1 ~~ HashRef # -> ""
	
	[]  ~~ HashRef[Int]           # -> ""
	{x=>1, y=>2}  ~~ HashRef[Int] # -> 1
	{x=>1, y=>""} ~~ HashRef[Int] # -> ""

=head2 Object`[O]

Blessed links.

	bless(\(my $val=10), "A1") ~~ Object # -> 1
	\(my $val=10) ~~ Object              # -> ""
	
	bless(\(my $val=10), "A1") ~~ Object["A1"] # -> 1
	bless(\(my $val=10), "A1") ~~ Object["B1"] # -> ""

=head2 Me

Blessed references to objects of the current package.

	package A1 {
		use Aion;
		bless({}, __PACKAGE__) ~~ Me  # -> 1
		bless({}, "A2") ~~ Me         # -> ""
	}

=head2 Map[K, V]

Like C<HashRef>, but with a key type.

	{} ~~ Map[Int, Int]               # -> 1
	{5 => 3} ~~ Map[Int, Int]         # -> 1

lib/Aion/Types.pm  view on Meta::CPAN

An object or class has listed methods. In addition to them, there may be others.

	package HasMethodsExample {
		sub x1 {}
		sub x2 {}
	}
	
	"HasMethodsExample" ~~ HasMethods[qw/x1 x2/]			# -> 1
	bless({}, "HasMethodsExample") ~~ HasMethods[qw/x1 x2/] # -> 1
	bless({}, "HasMethodsExample") ~~ HasMethods[qw/x1/]	# -> 1
	"HasMethodsExample" ~~ HasMethods[qw/x3/]				# -> ""
	"HasMethodsExample" ~~ HasMethods[qw/x1 x2 x3/]			# -> ""
	"HasMethodsExample" ~~ HasMethods[qw/x1 x3/]			# -> ""

=head2 Overload`[op...]

An object or class with overloaded operators.

	package OverloadExample {
		use overload '""' => sub { "abc" };
	}
	
	"OverloadExample" ~~ Overload            # -> 1
	bless({}, "OverloadExample") ~~ Overload # -> 1
	"A" ~~ Overload                          # -> ""
	bless({}, "A") ~~ Overload               # -> ""

And the specified operators are overloaded.

	"OverloadExample" ~~ Overload['""'] # -> 1
	"OverloadExample" ~~ Overload['|']  # -> ""

=head2 InstanceOf[A...]

A class or object inherits classes from a list.

	package Animal {}
	package Cat { our @ISA = qw/Animal/ }
	package Tiger { our @ISA = qw/Cat/ }
	
	
	"Tiger" ~~ InstanceOf['Animal', 'Cat'] # -> 1
	"Tiger" ~~ InstanceOf['Tiger']         # -> 1
	"Tiger" ~~ InstanceOf['Cat', 'Dog']    # -> ""

=head2 ConsumerOf[A...]

A class or object has the specified roles.

	package NoneExample {}
	package RoleExample { sub DOES { $_[1] ~~ [qw/Role1 Role2/] } }
	
	'RoleExample' ~~ ConsumerOf[qw/Role1/] # -> 1
	'RoleExample' ~~ ConsumerOf[qw/Role2 Role1/] # -> 1
	bless({}, 'RoleExample') ~~ ConsumerOf[qw/Role3 Role2 Role1/] # -> ""
	
	'NoneExample' ~~ ConsumerOf[qw/Role1/] # -> ""

=head2 BoolLike

Tests for 1, 0, "", undef, or an object with an overloaded C<bool> or C<0+> operator as C<JSON::PP::Boolean>. In the second case, it calls the C<0+> operator and checks the result as C<Bool>.

C<BoolLike> calls the C<0+> operator and checks the result.

	package BoolLikeExample {
		use overload '0+' => sub { ${$_[0]} };
	}
	
	bless(\(my $x = 1 ), 'BoolLikeExample') ~~ BoolLike # -> 1
	bless(\(my $x = 11), 'BoolLikeExample') ~~ BoolLike # -> ""
	
	1 ~~ BoolLike     # -> 1
	0 ~~ BoolLike     # -> 1
	"" ~~ BoolLike    # -> 1
	undef ~~ BoolLike # -> 1
	
	package BoolLike2Example {
		use overload 'bool' => sub { ${$_[0]} };
	}
	
	bless(\(my $x = 1 ), 'BoolLike2Example') ~~ BoolLike # -> 1
	bless(\(my $x = 11), 'BoolLike2Example') ~~ BoolLike # -> 1

=head2 StrLike

A string or object overloaded with the C<""> operator.

	"" ~~ StrLike # -> 1
	
	package StrLikeExample {
		use overload '""' => sub { "abc" };
	}
	
	bless({}, "StrLikeExample") ~~ StrLike # -> 1
	
	{} ~~ StrLike # -> ""

=head2 RegexpLike

A regular expression or object with an overload of the C<qr> operator.

	ref(qr//)  # => Regexp
	Scalar::Util::reftype(qr//) # => REGEXP
	
	my $regex = bless qr//, "A";
	Scalar::Util::reftype($regex) # => REGEXP
	
	$regex ~~ RegexpLike # -> 1
	qr// ~~ RegexpLike   # -> 1
	"" ~~ RegexpLike     # -> ""
	
	package RegexpLikeExample {
	 use overload 'qr' => sub { qr/abc/ };
	}
	
	"RegexpLikeExample" ~~ RegexpLike # -> ""
	bless({}, "RegexpLikeExample") ~~ RegexpLike # -> 1

=head2 CodeLike

A subroutine or object with an overload of the C<&{}> operator.

	sub {} ~~ CodeLike     # -> 1
	\&CodeLike ~~ CodeLike # -> 1
	{} ~~ CodeLike         # -> ""

=head2 ArrayLike`[A]

Arrays or objects with an overloaded operator or C<@{}>.

	{} ~~ ArrayLike      # -> ""
	{} ~~ ArrayLike[Int] # -> ""
	
	[] ~~ ArrayLike # -> 1
	
	package ArrayLikeExample {
		use overload '@{}' => sub {
			shift->{array} //= []
		};
	}
	
	my $x = bless {}, 'ArrayLikeExample';
	$x->[1] = 12;
	$x->{array} # --> [undef, 12]
	
	$x ~~ ArrayLike # -> 1
	
	$x ~~ ArrayLike[Int] # -> ""
	
	$x->[0] = 13;
	$x ~~ ArrayLike[Int] # -> 1

=head2 HashLike`[A]

Hashes or objects with the C<%{}> operator overloaded.

	{} ~~ HashLike  # -> 1
	[] ~~ HashLike  # -> ""
	[] ~~ HashLike[Int] # -> ""
	
	package HashLikeExample {
		use overload '%{}' => sub {
			shift->[0] //= {}
		};
	}
	
	my $x = bless [], 'HashLikeExample';
	$x->{key} = 12.3;
	$x->[0]  # --> {key => 12.3}
	
	$x ~~ HashLike      # -> 1
	$x ~~ HashLike[Int] # -> ""
	$x ~~ HashLike[Num] # -> 1

=head1 Coerces

=head2 Join[R] as Str

String type with conversion of arrays to a string through a delimiter.

	Join([' '])->coerce([qw/a b c/]) # => a b c
	
	package JoinExample { use Aion;
		has s => (isa => Join[', '], coerce => 1);
	}
	
	JoinExample->new(s => [qw/a b c/])->s # => a, b, c
	
	JoinExample->new(s => 'string')->s # => string

=head2 Split[S] as ArrayRef

	Split([' '])->coerce('a b c') # --> [qw/a b c/]
	
	package SplitExample { use Aion;
		has s => (isa => Split[qr/\s*,\s*/], coerce => 1);
	}
	
	SplitExample->new(s => 'a, b, c')->s # --> [qw/a b c/]

=head1 AUTHOR

Yaroslav O. Kosmina LL<mailto:dart@cpan.org>



( run in 1.526 second using v1.01-cache-2.11-cpan-d80b1682f3f )