File Coverage

blib/lib/Defaults/Modern.pm
Criterion Covered Total %
statement 121 121 100.0
branch 14 16 87.5
condition 2 3 66.6
subroutine 25 25 100.0
pod n/a
total 162 165 98.1


line stmt bran cond sub pod time code
1             package Defaults::Modern;
2             $Defaults::Modern::VERSION = '0.009003';
3 1     1   13290 use v5.14;
  1         2  
4              
5 1     1   434 use strictures 2;
  1         1123  
  1         45  
6 1     1   530 no indirect ':fatal';
  1         798  
  1         4  
7 1     1   464 no bareword::filehandles;
  1         2824  
  1         4  
8              
9 1     1   465 use Module::Runtime 'use_package_optimistically';
  1         1214  
  1         5  
10 1     1   414 use Try::Tiny;
  1         1583  
  1         48  
11 1     1   369 use Import::Into;
  1         351  
  1         26  
12              
13              
14 1     1   4 use Carp ();
  1         1  
  1         14  
15 1     1   3 use feature ();
  1         0  
  1         12  
16 1     1   468 use true ();
  1         6595  
  1         23  
17              
18 1     1   361 use match::simple ();
  1         4170  
  1         19  
19              
20 1     1   352 use Defaults::Modern::Define ();
  1         3  
  1         24  
21 1     1   466 use Function::Parameters ();
  1         1758  
  1         22  
22 1     1   408 use List::Objects::WithUtils ();
  1         695  
  1         19  
23 1     1   690 use Path::Tiny ();
  1         8263  
  1         41  
24 1     1   385 use PerlX::Maybe ();
  1         1597  
  1         18  
25 1     1   4 use Scalar::Util ();
  1         1  
  1         13  
26 1     1   367 use Switch::Plain ();
  1         569  
  1         20  
27              
28 1     1   474 use Types::Standard ();
  1         46563  
  1         30  
29 1     1   382 use Types::Path::Tiny ();
  1         16806  
  1         30  
30 1     1   396 use Type::Registry ();
  1         18806  
  1         26  
31 1     1   7 use Type::Utils ();
  1         2  
  1         13  
32 1     1   522 use List::Objects::Types ();
  1         67894  
  1         742  
33              
34              
35             sub import {
36 9     9   14316 my $class = shift;
37 9         20 my $pkg = caller;
38              
39             state $known = +{
40 9         17 map {; $_ => 1 } qw/
  3         5  
41             all
42             autobox_lists
43             moo
44             /
45             };
46              
47 9         11 my %params;
48 9         12 my $idx = 0;
49 9         28 my $typelibs;
50 9         20 PARAM: for my $item (@_) {
51 9         16 my $current = $idx++;
52 9 100 66     57 if ($item eq 'with_types' || $item eq '-with_types') {
53 2         6 $typelibs = $_[$idx];
54 2         5 splice @_, $current, 2;
55 2 100       5 if (ref $typelibs) {
56 1 50       7 Carp::croak "with_types should be an ARRAY, got $typelibs"
57             if Scalar::Util::reftype($typelibs) ne 'ARRAY';
58             } else {
59 1         2 $typelibs = [ $typelibs ]
60             }
61             next PARAM
62 2         4 }
63              
64 7         32 my $opt = lc($item =~ s/^(?:[-:])//r);
65 7 100       269 Carp::croak "$class does not export $opt" unless $known->{$opt};
66              
67 6 100       19 if ($opt eq 'all') {
68 4         11 $params{$_} = 1 for grep {; $_ ne 'all' } keys %$known;
  12         25  
69             next PARAM
70 4         9 }
71              
72 2         4 $params{$opt} = 1;
73             }
74              
75             # Us
76 8         46 Defaults::Modern::Define->import::into($pkg);
77              
78             # Core
79 8         328 Carp->import::into($pkg,
80             qw/carp croak confess/,
81             );
82              
83 8         1420 Scalar::Util->import::into($pkg,
84             qw/blessed reftype weaken/,
85             );
86            
87             # Pragmas
88 8         2081 strictures->import::into($pkg, version => 2);
89 8         2209 bareword::filehandles->unimport;
90 8         67 indirect->unimport(':fatal');
91 8         197 warnings->unimport('once');
92 8 50       26 if ($] >= 5.018) {
93 8         36 warnings->unimport('experimental');
94             }
95              
96 8         352 feature->import(':5.14');
97 8         81 feature->unimport('switch');
98              
99 8         40 match::simple->import::into($pkg);
100 8         3461 true->import;
101              
102             # External functionality
103              
104             state $fp_defaults = +{
105             strict => 1,
106             default_arguments => 1,
107             named_parameters => 1,
108             types => 1,
109             reify_type => sub {
110 6     6   2170 state $guard = do { require Type::Utils };
  1         7  
111 6         30 Type::Utils::dwim_type($_[0], for => $_[1])
112             },
113 8         3443 };
114              
115 8         118 Function::Parameters->import::into( $pkg,
116             +{
117             fun => {
118             name => 'optional',
119             %$fp_defaults
120             },
121             method => {
122             name => 'required',
123             attributes => ':method',
124             shift => '$self',
125             invocant => 1,
126             %$fp_defaults
127             }
128             }
129             );
130              
131 8         3329 Path::Tiny->import::into($pkg, 'path');
132              
133 8         1290 PerlX::Maybe->import::into($pkg, qw/maybe provided/);
134              
135 8         1231 Try::Tiny->import::into($pkg);
136 8         1345 Switch::Plain->import;
137              
138             $params{autobox_lists} ?
139 8 100       208 List::Objects::WithUtils->import::into($pkg, 'all')
140             : List::Objects::WithUtils->import::into($pkg);
141              
142             # Types
143 8         17324 state $mytypelibs = [ qw/
144             Types::Standard
145             Types::Path::Tiny
146             List::Objects::Types
147             / ];
148              
149 8         18 for my $typelib (@$mytypelibs, @$typelibs) {
150 26         230889 use_package_optimistically($typelib)->import::into($pkg, -all);
151             # Irrelevant with Type::Tiny-1.x ->
152             # try {
153             # Type::Registry->for_class($pkg)->add_types($typelib);
154             # } catch {
155             # Usually conflicts; whine but prefer user's previous imports:
156             # Carp::carp($_)
157             # };
158             }
159              
160 8 100       28506 if (defined $params{moo}) {
161 5         641 require Moo;
162 5         5154 Moo->import::into($pkg);
163             }
164              
165             $class
166 8         4965 }
167              
168             1;
169              
170             =pod
171              
172             =head1 NAME
173              
174             Defaults::Modern - Yet another approach to modernistic Perl
175              
176             =head1 SYNOPSIS
177              
178             use Defaults::Modern;
179              
180             # Function::Parameters + List::Objects::WithUtils + types ->
181             fun to_immutable ( (ArrayRef | ArrayObj) $arr ) {
182             # blessed() and confess() are available (amongst others):
183             my $immutable = immarray( blessed $arr ? $arr->all : @$arr );
184             confess 'No items in array!' unless $immutable->has_any;
185             $immutable
186             }
187              
188             package My::Foo {
189             use Defaults::Modern;
190              
191             # define keyword for defining constants ->
192             define ARRAY_MAX = 10;
193              
194             # Moo(se) with types ->
195             use Moo;
196              
197             has myarray => (
198             isa => ArrayObj,
199             is => 'ro',
200             writer => '_set_myarray',
201             coerce => 1,
202             default => sub { [] },
203             );
204              
205             # Method with optional positional param and implicit $self ->
206             method slice_to_max (Int $max = -1) {
207             my $arr = $self->myarray;
208             $self->_set_myarray(
209             $arr->sliced( 0 .. $max >= 0 ? $max : ARRAY_MAX )
210             )
211             }
212             }
213              
214             # Optionally autobox list-type refs via List::Objects::WithUtils ->
215             use Defaults::Modern 'autobox_lists';
216             my $obj = +{ foo => 'bar', baz => 'quux' }->inflate;
217             my $baz = $obj->baz;
218              
219             # See DESCRIPTION for complete details on imported functionality.
220              
221             =head1 DESCRIPTION
222              
223             Yet another approach to writing Perl in a modern style.
224              
225             . . . also saves me extensive typing ;-)
226              
227             When you C, you get:
228              
229             =over
230              
231             =item *
232              
233             L (version 2), which enables L and makes most warnings
234             fatal; additionally L and L method calls are
235             disallowed explicitly (not just in development environments)
236              
237             =item *
238              
239             The C feature set (C, C, C, C) -- except for
240             C, which is deprecated in newer perls (and L is
241             provided anyway).
242              
243             C warnings are also disabled on C.
244              
245             =item *
246              
247             B, B, and B error reporting tools from L
248              
249             =item *
250              
251             B, B, and B utilities from L
252              
253             =item *
254              
255             All of the L object constructors (B,
256             B, B, B, B, B, B,
257             B)
258              
259             =item *
260              
261             B and B keywords from L
262              
263             =item *
264              
265             The full L set and L -- useful in
266             combination with L (see the L and
267             L POD)
268              
269             =item *
270              
271             B and B from L
272              
273             =item *
274              
275             The B object constructor from L and related types/coercions
276             from L
277              
278             =item *
279              
280             B and B definedness-checking syntax sugar from L
281              
282             =item *
283              
284             A B keyword for defining constants based on L
285              
286             =item *
287              
288             The B<|M|> match operator from L
289              
290             =item *
291              
292             The B and B switch/case constructs from L
293              
294             =item *
295              
296             L.pm so you can skip adding '1;' to all of your modules
297              
298             =back
299              
300             If you want to automatically load (shown here with the '-all' import tag, as
301             well) and register other L compatible libraries (see
302             L), they can be specified at import time:
303              
304             use Defaults::Modern
305             -all,
306             -with_types => [ 'Types::Mine' ],
307              
308             This feature is unnecessary with L version 1.x and higher, which
309             will automatically register L-based types in the caller's
310             L.
311              
312             If you import the tag C, ARRAY and HASH type references are autoboxed
313             via L:
314              
315             use Defaults::Modern 'autobox_lists';
316             my $itr = [ 1 .. 10 ]->natatime(2);
317              
318             L version 2+ is depended upon in order to guarantee availability, but not
319             automatically imported:
320              
321             use Defaults::Modern;
322             use Moo;
323              
324             has foo => (
325             is => 'ro',
326             isa => ArrayObj,
327             coerce => 1,
328             default => sub { [] },
329             );
330              
331             (If you're building classes, you may want to look into L /
332             L or similar -- L imports an awful lot of
333             Stuff. L may be nicer to work with.)
334              
335             =head1 SEE ALSO
336              
337             This package just glues together useful parts of CPAN, the
338             most visible portions of which come from the following modules:
339              
340             L
341              
342             L
343              
344             L and L
345              
346             L
347              
348             L
349              
350             L
351              
352             L
353              
354             L
355              
356             L
357              
358             L
359              
360             L
361              
362             =head1 AUTHOR
363              
364             Jon Portnoy
365              
366             Licensed under the same terms as Perl.
367              
368             Inspired by L and L.
369              
370             The code backing the B keyword is forked from TOBYINK's
371             L to avoid the L dependency and is copyright Toby
372             Inkster.
373              
374             =cut
375              
376             # vim: ts=2 sw=2 et sts=2 ft=perl