%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/opti/perl/usr/man/man3/
Upload File :
Create Path :
Current File : /home/opti/perl/usr/man/man3/Type::Tiny::Manual::Coercions.3pm

.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
.    if \nF \{
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
.    \" fudge factors for nroff and troff
.if n \{\
.    ds #H 0
.    ds #V .8m
.    ds #F .3m
.    ds #[ \f1
.    ds #] \fP
.\}
.if t \{\
.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
.    ds #V .6m
.    ds #F 0
.    ds #[ \&
.    ds #] \&
.\}
.    \" simple accents for nroff and troff
.if n \{\
.    ds ' \&
.    ds ` \&
.    ds ^ \&
.    ds , \&
.    ds ~ ~
.    ds /
.\}
.if t \{\
.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
.    \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
.    \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
.    \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
.    ds : e
.    ds 8 ss
.    ds o a
.    ds d- d\h'-1'\(ga
.    ds D- D\h'-1'\(hy
.    ds th \o'bp'
.    ds Th \o'LP'
.    ds ae ae
.    ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "Type::Tiny::Manual::Coercions 3"
.TH Type::Tiny::Manual::Coercions 3 "2018-07-29" "perl v5.16.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
Type::Tiny::Manual::Coercions \- adding coercions to type constraints
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBStop! Don't do it!\fR
.PP
\&\s-1OK,\s0 it's fairly common practice in Moose/Mouse code to define
coercions for type constraints. For example, suppose we define a type
constraint in a type library:
.PP
.Vb 1
\&   class_type PathTiny, { class => "Path::Tiny" };
.Ve
.PP
We may wish to define a coercion (i.e. a conversion routine) to handle
strings, and convert them into Path::Tiny objects:
.PP
.Vb 2
\&   coerce PathTiny,
\&      from Str, via { "Path::Tiny"\->new($_) };
.Ve
.PP
However, there are good reasons to avoid this practice. It ties the
coercion routine to the type constraint. Any people wishing to use your
\&\f(CW\*(C`PathTiny\*(C'\fR type constraint need to buy in to your idea of how they
should be coerced from \f(CW\*(C`Str\*(C'\fR. With Path::Tiny this is unlikely to
be controversial, however consider:
.PP
.Vb 2
\&   coerce ArrayRef,
\&      from Str, via { [split /\en/] };
.Ve
.PP
In one part of the application (dealing with parsing log files for
instance), this could be legitimate. But another part (dealing with
logins perhaps) might prefer to split on colons. Another (dealing with
web services) might attempt to parse the string as a \s-1JSON\s0 array.
.PP
If all these coercions have attached themselves to the \f(CW\*(C`ArrayRef\*(C'\fR
type constraint, coercing a string becomes a complicated proposition!
In a large application where coercions are defined across many different
files, the application can start to suffer from \*(L"spooky action at a
distance\*(R".
.PP
In the interests of Moose-compatibility, Type::Tiny and Type::Coercion
do allow you to define coercions this way, but they also provide an
alternative that you should consider: \f(CW\*(C`plus_coercions\*(C'\fR.
.SS "plus_coercions"
.IX Subsection "plus_coercions"
Type::Tiny offers a method \f(CW\*(C`plus_coercions\*(C'\fR which constructs a new
anonymous type constraint, but with additional coercions.
.PP
In our earlier example, we'd define the \f(CW\*(C`PathTiny\*(C'\fR type constraint
in our type library as before:
.PP
.Vb 1
\&   class_type PathTiny, { class => "Path::Tiny" };
.Ve
.PP
But then not define any coercions for it. Later, when using the
type constraint in a class, we can add coercions:
.PP
.Vb 4
\&   my $ConfigFileType = PathTiny\->plus_coercions(
\&      Str,   sub { "Path::Tiny"\->new($_) },
\&      Undef, sub { "Path::Tiny"\->new("/etc/myapp/default.conf") },
\&   );
\&   
\&   has config_file => (
\&      is     => "ro",
\&      isa    => $ConfigFileType,
\&      coerce => 1,
\&   );
.Ve
.PP
Where the \f(CW\*(C`PathTiny\*(C'\fR constraint is used in another part of the code, it
will not see these coercions, because they were added to the new anonymous
type constraint, not to the \f(CW\*(C`PathTiny\*(C'\fR constraint itself!
.SS "Named Coercions"
.IX Subsection "Named Coercions"
A type library may define a named set of coercions to a particular
type. For example, let's define that coercion from \f(CW\*(C`Str\*(C'\fR to \f(CW\*(C`ArrayRef\*(C'\fR:
.PP
.Vb 3
\&   declare_coercion "LinesFromStr",
\&      to_type ArrayRef,
\&      from Str, q{ [split /\en/] };
.Ve
.PP
Now we can import that coercion using a name, and it makes our code
look a little cleaner:
.PP
.Vb 2
\&   use Types::Standard qw(ArrayRef);
\&   use MyApp::Types qw(LinesFromStr);
\&   
\&   has lines => (
\&      is     => "ro",
\&      isa    => ArrayRef\->plus_coercions(LinesFromStr),
\&      coerce => 1,
\&   );
.Ve
.SS "Parameterized Coercions"
.IX Subsection "Parameterized Coercions"
Parameterized type constraints are familiar from Moose. For example, an
arrayref of integers:
.PP
.Vb 1
\&   ArrayRef[Int]
.Ve
.PP
Type::Coercion supports parameterized named coercions too. For example,
the following type constraint has a coercion from strings that splits them
into lines:
.PP
.Vb 1
\&   use Types::Standard qw( ArrayRef Split );
\&   
\&   my $ArrayOfLines = ArrayRef\->plus_coercions( Split[ qr{\en} ] );
.Ve
.PP
Viewing the source code for Types::Standard should give you hints as
to how they are implemented.
.SS "plus_fallback_coercions, minus_coercions and no_coercions"
.IX Subsection "plus_fallback_coercions, minus_coercions and no_coercions"
Getting back to the \f(CW\*(C`plus_coercions\*(C'\fR method, there are some other
methods that perform coercion maths.
.PP
\&\f(CW\*(C`plus_fallback_coercions\*(C'\fR is the same as \f(CW\*(C`plus_coercions\*(C'\fR but the
added coercions have a lower priority than any existing coercions.
.PP
\&\f(CW\*(C`minus_coercions\*(C'\fR can be given a list of type constraints that we
wish to ignore coercions for. Imagine our \f(CW\*(C`PathTiny\*(C'\fR constraint already
has a coercion from \f(CW\*(C`Str\*(C'\fR, then the following creates a new anonymous
type constraint without that coercion:
.PP
.Vb 1
\&   PathTiny\->minus_coercions(Str)
.Ve
.PP
\&\f(CW\*(C`no_coercions\*(C'\fR gives us a new type anonymous constraint without any
of its parents coercions. This is useful as a way to create a blank slate
for a subsequent \f(CW\*(C`plus_coercions\*(C'\fR:
.PP
.Vb 1
\&   PathTiny\->no_coercions\->plus_coercions(...)
.Ve
.SS "plus_constructors"
.IX Subsection "plus_constructors"
The \f(CW\*(C`plus_constructors\*(C'\fR method defined in Type::Tiny::Class is sugar
for \f(CW\*(C`plus_coercions\*(C'\fR. The following two are the same:
.PP
.Vb 1
\&   PathTiny\->plus_coercions(Str, q{ Path::Tiny\->new($_) })
\&   
\&   PathTiny\->plus_constructors(Str, "new");
.Ve
.ie n .SS """Deep"" Coercions"
.el .SS "``Deep'' Coercions"
.IX Subsection "Deep Coercions"
Certain parameterized type constraints can automatically acquire coercions
if their parameters have coercions. For example:
.PP
.Vb 1
\&   ArrayRef[ Int\->plus_coercions(Num, q{int($_)}) ]
.Ve
.PP
\&... does what you mean!
.PP
The parameterized type constraints that do this magic include the following
ones from Types::Standard:
.IP "\(bu" 4
\&\f(CW\*(C`ScalarRef\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`ArrayRef\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`HashRef\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`Map\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`Tuple\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`CycleTuple\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`Dict\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`Optional\*(C'\fR
.IP "\(bu" 4
\&\f(CW\*(C`Maybe\*(C'\fR
.PP
Imagine we're declaring a type library:
.PP
.Vb 1
\&   declare Paths, as ArrayRef[PathTiny];
.Ve
.PP
The \f(CW\*(C`PathTiny\*(C'\fR type (declared earlier in the tutorial) has a coercion
from \f(CW\*(C`Str\*(C'\fR, so \f(CW\*(C`Paths\*(C'\fR should be able to coerce from an arrayref of
strings, right?
.PP
\&\fBWrong!\fR \f(CW\*(C`ArrayRef[PathTiny]\*(C'\fR can coerce from an arrayref of
strings, but \f(CW\*(C`Paths\*(C'\fR is a separate type constraint which, although it
inherits from \f(CW\*(C`ArrayRef[PathTiny]\*(C'\fR has its own (currently empty)
set of coercions.
.PP
Because that is often not what you want, Type::Tiny provides a shortcut
when declaring a subtype to copy the parent type constraint's coercions:
.PP
.Vb 1
\&   declare Paths, as ArrayRef[PathTiny], coercion => 1;
.Ve
.PP
Now \f(CW\*(C`Paths\*(C'\fR can coerce from an arrayref of strings.
.PP
\fIDeep Caveat\fR
.IX Subsection "Deep Caveat"
.PP
Currently there exists ill-defined behaviour resulting from mixing deep
coercions and mutable (non-frozen) coercions. Consider the following:
.PP
.Vb 3
\&   class_type PathTiny, { class => "Path::Tiny" };
\&   coerce PathTiny,
\&      from Str, via { "Path::Tiny"\->new($_) };
\&   
\&   declare Paths, as ArrayRef[PathTiny], coercion => 1;
\&   
\&   coerce PathTiny,
\&      from InstanceOf["My::File"], via { $_\->get_path };
.Ve
.PP
An arrayref of strings can now be coerced to an arrayref of Path::Tiny
objects, but is it also now possible to coerce an arrayref of My::File
objects to an arrayref of Path::Tiny objects?
.PP
Currently the answer is \*(L"no\*(R", but this is mostly down to implementation
details. It's not clear what the best way to behave in this situation
is, and it could start working at some point in the future.
.PP
You should avoid falling into this trap by following the advice found
under \*(L"The (Lack of) Zen of Coercions\*(R".
.SS "Chained Coercions"
.IX Subsection "Chained Coercions"
Consider the following type library:
.PP
.Vb 10
\&   {
\&      package Types::Geometric;
\&      use Type::Library \-base, \-declare => qw(
\&         VectorArray
\&         VectorArray3D
\&         Point
\&         Point3D
\&      );
\&      use Type::Utils;
\&      use Types::Standard qw( Num Tuple InstanceOf );
\&      
\&      declare VectorArray,
\&         as Tuple[Num, Num];
\&      
\&      declare VectorArray3D,
\&         as Tuple[Num, Num, Num];
\&      
\&      coerce VectorArray3D,
\&         from VectorArray, via {
\&            [ @$_, 0 ];
\&         };
\&      
\&      class_type Point, { class => "Point" };
\&      
\&      coerce Point,
\&         from VectorArray, via {
\&            Point\->new(x => $_\->[0], y => $_\->[1]);
\&         };
\&      
\&      class_type Point3D, { class => "Point3D" };
\&      
\&      coerce Point3D,
\&         from VectorArray3D, via {
\&            Point3D\->new(x => $_\->[0], y => $_\->[1], z => $_\->[2]);
\&         },
\&         from Point, via {
\&            Point3D\->new(x => $_\->x, y => $_\->y, z => 0);
\&         };
\&   }
.Ve
.PP
Given an arrayref \f(CW\*(C`[1, 1]\*(C'\fR you might reasonably expect it to be
coercible to a \f(CW\*(C`Point3D\*(C'\fR object; it matches the type constraint
\&\f(CW\*(C`VectorArray\*(C'\fR so can be coerced to \f(CW\*(C`VectorArray3D\*(C'\fR and thus to
\&\f(CW\*(C`Point3D\*(C'\fR.
.PP
However, Type::Coercion does not automatically chain coercions
like this. Firstly, it would be incompatible with Moose's type coercion
system which does not chain coercions. Secondly, it's ambiguous; in our
example, the arrayref could be coerced along two different paths (via
\&\f(CW\*(C`VectorArray3D\*(C'\fR or via \f(CW\*(C`Point\*(C'\fR); in this case the end result would be
the same, but in other cases it might not. Thirdly, it runs the risk of
accidentally creating loops.
.PP
Doing the chaining manually though is pretty simple. Firstly, we'll
take note of the \f(CW\*(C`coercibles\*(C'\fR method in Type::Tiny. This method
called as \f(CW\*(C`VectorArray3D\->coercibles\*(C'\fR returns a type constraint
meaning "anything that can be coerced to a \f(CW\*(C`VectorArray3D\*(C'\fR".
.PP
So we can define the coercions for \f(CW\*(C`Point3D\*(C'\fR as:
.PP
.Vb 8
\&   coerce Point3D,
\&      from VectorArray3D\->coercibles, via {
\&         my $tmp = to_VectorArray3D($_);
\&         Point3D\->new(x => $tmp\->[0], y => $tmp\->[1], z => $tmp\->[2]);
\&      },
\&      from Point, via {
\&         Point3D\->new(x => $_\->x, y => $_\->y, z => 0);
\&      };
.Ve
.PP
\&... and now coercing from \f(CW\*(C`[1, 1]\*(C'\fR will work.
.SS "The (Lack of) Zen of Coercions"
.IX Subsection "The (Lack of) Zen of Coercions"
Coercions can lead to ugliness.
.PP
Let's say we define a type constraint \f(CW\*(C`Path\*(C'\fR which has a coercion from
\&\f(CW\*(C`Str\*(C'\fR. Now we define a class which uses that type constraint.
.PP
Now in another class, we define a coercion from \f(CW\*(C`ArrayRef\*(C'\fR to \f(CW\*(C`Path\*(C'\fR.
This kind of action at a distance is not really desirable. And in fact,
things will probably subtly break \- the first class may have already
built a constructor inlining a bunch of code from the coercion.
.PP
However, you too can achieve coercion zen by following these
three weird tricks <http://www.slate.com/articles/business/moneybox/2013/07/how_one_weird_trick_conquered_the_internet_what_happens_when_you_click_on.html>:
.IP "1." 4
If you want to define coercions for a type, do it \fIwithin your type
constraint library\fR, so the coercions are all defined before the
type constraint is ever used.
.IP "2." 4
At the end of your type constraint library, consider calling
\&\f(CW\*(C`$type\->coercion\->freeze\*(C'\fR on each type constraint that has a
coercion. This makes the type's coercions immutable. If anybody wants
to define any additional coercions, they'll have to create a child type
to do it with.
.Sp
A shortcut exists to do this on all types in your library:
.Sp
.Vb 1
\&   _\|_PACKAGE_\|_\->meta\->make_immutable;
.Ve
.IP "3." 4
Use \f(CW\*(C`plus_coercions\*(C'\fR and similar methods to easily create a child
type constraint of any existing type, and add more coercions to it.
Don't fiddle directly with the existing type constraint which may be
being used elsewhere.
.Sp
Note that these methods all return type constraint objects with
frozen (immutable) coercions.
.PP
That's it.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
Moose::Manual::BestPractices,
<http://www.catalyzed.org/2009/06/keeping\-your\-coercions\-to\-yourself.html>.
.SH "AUTHOR"
.IX Header "AUTHOR"
Toby Inkster <tobyink@cpan.org>.
.SH "COPYRIGHT AND LICENCE"
.IX Header "COPYRIGHT AND LICENCE"
This software is copyright (c) 2013\-2014, 2017\-2018 by Toby Inkster.
.PP
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
.SH "DISCLAIMER OF WARRANTIES"
.IX Header "DISCLAIMER OF WARRANTIES"
\&\s-1THIS PACKAGE IS PROVIDED \*(L"AS IS\*(R" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.\s0

Zerion Mini Shell 1.0