1MooseX::Extended(3) User Contributed Perl Documentation MooseX::Extended(3)
2
3
4
6 MooseX::Extended - Extend Moose with safe defaults and useful features
7
9 version 0.35
10
12 package My::Names {
13 use MooseX::Extended types => [qw(compile Num NonEmptyStr Str PositiveInt ArrayRef)];
14 use List::Util 'sum';
15
16 # the distinction between `param` and `field` makes it easier to
17 # see which are available to `new`
18 param _name => ( isa => NonEmptyStr, init_arg => 'name' );
19 param title => ( isa => Str, required => 0 );
20
21 # forbidden in the constructor
22 field created => ( isa => PositiveInt, default => sub {time} );
23
24 sub name ($self) {
25 my $title = $self->title;
26 my $name = $self->_name;
27 return $title ? "$title $name" : $name;
28 }
29
30 sub add ( $self, $args ) {
31 state $check = compile( ArrayRef [ Num, 1 ] ); # at least one number
32 ($args) = $check->($args);
33 return sum( $args->@* );
34 }
35
36 sub warnit ($self) {
37 carp("this is a warning");
38 }
39 }
40
42 This module is BETA code. It's feature-complete for release and has no
43 known bugs. We believe it's ready for production, but make no promises.
44
45 This is a quick overview. See MooseX::Extended::Manual::Tutorial for
46 more information.
47
48 This class attempts to create a safer version of Moose that defaults to
49 read-only attributes and is easier to read and write.
50
51 It tries to bring some of the lessons learned from the Corinna project
52 <https://github.com/Ovid/Cor>, while acknowledging that you can't
53 always get what you want (such as true encapsulation and true methods).
54
55 This:
56
57 package My::Class {
58 use MooseX::Extended;
59
60 ... your code here
61 }
62
63 Is sort of the equivalent to:
64
65 package My::Class {
66 use v5.20.0;
67 use Moose;
68 use MooseX::StrictConstructor;
69 use feature qw( signatures postderef postderef_qq );
70 no warnings qw( experimental::signatures experimental::postderef );
71 use namespace::autoclean;
72 use Carp;
73 use mro 'c3';
74
75 ... your code here
76
77 __PACKAGE__->meta->make_immutable;
78 }
79 1;
80
81 It also exports two functions which are similar to Moose "has": "param"
82 and "field".
83
84 A "param" is a required parameter (defaults may be used). A "field" is
85 not intended to be passed to the constructor.
86
87 Note: the "has" function is still available, even if it's not needed.
88 Unlike "param" and "field", it still requires an "is" option.
89
90 Also, while your author likes the postfix block syntax, it's not
91 required. You can even safely inline multiple packages in the same
92 file:
93
94 package My::Point;
95 use MooseX::Extended types => 'Num';
96
97 param [ 'x', 'y' ] => ( isa => Num );
98
99 package My::Point::Mutable;
100 use MooseX::Extended;
101 extends 'My::Point';
102
103 param [ '+x', '+y' ] => ( writer => 1, clearer => 1, default => 0 );
104
105 sub invert ($self) {
106 my ( $x, $y ) = ( $self->x, $self->y );
107 $self->set_x($y);
108 $self->set_y($x);
109 }
110
111 # MooseX::Extended will cause this to return true, even if we try to return
112 # false
113 0;
114
116 You may pass an import list to MooseX::Extended.
117
118 use MooseX::Extended
119 excludes => [qw/StrictConstructor carp/], # I don't want these features
120 types => [qw/compile PositiveInt HashRef/]; # I want these type tools
121
122 "types"
123 Allows you to import any types provided by MooseX::Extended::Types.
124
125 This:
126
127 use MooseX::Extended::Role types => [qw/compile PositiveInt HashRef/];
128
129 Is identical to this:
130
131 use MooseX::Extended::Role;
132 use MooseX::Extended::Types qw( compile PositiveInt HashRef );
133
134 "excludes"
135 You may find some features to be annoying, or even cause potential bugs
136 (e.g., if you have a "croak" method, our importing of "Carp::croak"
137 will be a problem.
138
139 A single argument to "excludes" can be a string. Multiple "excludes"
140 require an array reference:
141
142 use MooseX::Extended excludes => [qw/StrictConstructor autoclean/];
143
144 You can exclude the following:
145
146 • "StrictConstructor"
147
148 use MooseX::Extended excludes => 'StrictConstructor';
149
150 Excluding this will no longer import "MooseX::StrictConstructor".
151
152 • "autoclean"
153
154 use MooseX::Extended excludes => 'autoclean';
155
156 Excluding this will no longer import "namespace::autoclean".
157
158 • "c3"
159
160 use MooseX::Extended excludes => 'c3';
161
162 Excluding this will no longer apply the C3 mro.
163
164 • "carp"
165
166 use MooseX::Extended excludes => 'carp';
167
168 Excluding this will no longer import "Carp::croak" and
169 "Carp::carp".
170
171 • "immutable"
172
173 use MooseX::Extended excludes => 'immutable';
174
175 Excluding this will no longer make your class immutable.
176
177 • "true"
178
179 use MooseX::Extended excludes => 'true';
180
181 Excluding this will require your module to end in a true value.
182
183 • "param"
184
185 use MooseX::Extended excludes => 'param';
186
187 Excluding this will make the "param" function unavailable.
188
189 • "field"
190
191 use MooseX::Extended excludes => 'field';
192
193 Excluding this will make the "field" function unavailable.
194
195 "includes"
196 Several optional features of MooseX::Extended make this module much
197 more powerful. For example, to include try/catch and a "method"
198 keyword:
199
200 use MooseX::Extended includes => [ 'method', 'try' ];
201
202 A single argument to "includes" can be a string. Multiple "includes"
203 require an array reference:
204
205 use MooseX::Extended includes => [qw/method try/];
206
207 See MooseX::Extended::Manual::Includes for more information.
208
210 Let's say you've settled on the following feature set:
211
212 use MooseX::Extended
213 excludes => [qw/StrictConstructor carp/],
214 includes => 'method',
215 types => ':Standard';
216
217 And you keep typing that over and over. We've removed a lot of
218 boilerplate, but we've added different boilerplate. Instead, just
219 create "My::Custom::Moose" and "use My::Custom::Moose;". See
220 MooseX::Extended::Custom for details.
221
223 Making Your Class Immutable
224 You no longer need to end your Moose classes with:
225
226 __PACKAGE__->meta->make_immutable;
227
228 That prevents further changes to the class and provides some
229 optimizations to make the code run much faster. However, it's somewhat
230 annoying to type. We do this for you, via B::Hooks::AtRuntime. You no
231 longer need to do this yourself.
232
233 Making Your Instance Immutable
234 By default, attributes defined via "param" and "field" are read-only.
235 However, if they contain a reference, you can fetch the reference,
236 mutate it, and now everyone with a copy of that reference has mutated
237 state.
238
239 To handle that, we offer a new "clone => $clone_type" pair for
240 attributes.
241
242 See the MooseX::Extended::Manual::Cloning documentation.
243
245 Object construction for MooseX::Extended is identical to Moose because
246 MooseX::Extended is Moose, so no changes are needed. However, in
247 addition to "has", we also provide "param" and "field" attributes, both
248 of which are "is => 'ro'" by default.
249
250 The "param" is required, whether by passing it to the constructor, or
251 using "default" or "builder".
252
253 The "field" is forbidden in the constructor and is lazy if it has a
254 builder, because that builder is often dependent on attributes set in
255 the constructor (and why call it if it's not used?).
256
257 Here's a short example:
258
259 package Class::Name {
260 use MooseX::Extended types => [qw(compile Num NonEmptyStr Str)];
261
262 # these default to 'ro' (but you can override that) and are required
263 param _name => ( isa => NonEmptyStr, init_arg => 'name' );
264 param title => ( isa => Str, required => 0 );
265
266 # fields must never be passed to the constructor
267 # note that ->title and ->name are guaranteed to be set before
268 # this because fields are lazy by default
269 field name => (
270 isa => NonEmptyStr,
271 default => sub ($self) {
272 my $title = $self->title;
273 my $name = $self->_name;
274 return $title ? "$title $name" : $name;
275 },
276 );
277 }
278
279 See MooseX::Extended::Manual::Construction for a full explanation.
280
282 When using "field" or "param", we have some attribute shortcuts:
283
284 param name => (
285 isa => NonEmptyStr,
286 writer => 1, # set_name
287 reader => 1, # get_name
288 predicate => 1, # has_name
289 clearer => 1, # clear_name
290 builder => 1, # _build_name
291 );
292
293 sub _build_name ($self) {
294 ...
295 }
296
297 You can also do this:
298
299 param name ( isa => NonEmptyStr, builder => sub {...} );
300
301 That's the same as:
302
303 param name ( isa => NonEmptyStr, builder => '_build_name' );
304
305 sub _build_name {...}
306
307 See MooseX::Extended::Manual::Shortcuts for a full explanation.
308
310 The following Moose code will print "WhoAmI". However, the second
311 attribute name is clearly invalid.
312
313 package Some::Class {
314 use Moose;
315
316 has name => ( is => 'ro' );
317 has '-bad' => ( is => 'ro' );
318 }
319
320 my $object = Some::Class->new( name => 'WhoAmI' );
321 say $object->name;
322
323 "MooseX::Extended" will throw a
324 Moose::Exception::InvalidAttributeDefinition exception if it encounters
325 an illegal method name for an attribute.
326
327 This also applies to various attributes which allow method names, such
328 as "clone", "builder", "clearer", "writer", "reader", and "predicate".
329
330 Trying to pass a defined "init_arg" to "field" will also throw this
331 exception, unless the init_arg begins with an underscore. (It is
332 sometimes useful to be able to define an "init_arg" for unit testing.)
333
335 None known at this time.
336
338 • MooseX::Extended::Manual::Tutorial
339
340 • MooseX::Extended::Manual::Overview
341
342 • MooseX::Extended::Manual::Construction
343
344 • MooseX::Extended::Manual::Includes
345
346 • MooseX::Extended::Manual::Shortcuts
347
348 • MooseX::Extended::Manual::Cloning
349
351 • MooseX::Extended::Types is included in the distribution.
352
353 This provides core types for you.
354
355 • MooseX::Extended::Role is included in the distribution.
356
357 "MooseX::Extended", but for roles.
358
360 Some of this may just be wishful thinking. Some of this would be
361 interesting if others would like to collaborate.
362
363 Configurable Types
364 We provide "MooseX::Extended::Types" for convenience, along with the
365 "declare" function. We should write up (and test) examples of extending
366 it.
367
368 "BEGIN::Lift"
369 This idea maybe belongs in "MooseX::Extended::OverKill", but ...
370
371 Quite often you see things like this:
372
373 BEGIN { extends 'Some::Parent' }
374
375 Or this:
376
377 sub serial_number; # required by a role, must be compile-time
378 has serial_number => ( ... );
379
380 In fact, there are a variety of Moose functions which would work better
381 if they ran at compile-time instead of runtime, making them look a
382 touch more like native functions. My various attempts at solving this
383 have failed, but I confess I didn't try too hard.
384
386 There are a few things you might be interested to know about this
387 module when evaluating it.
388
389 Most of this is written with bog-standard Moose, so there's nothing
390 terribly weird inside, but you may wish to note that we use
391 B::Hooks::AtRuntime and true. They seem sane, but caveat emptor.
392
394 • Corinna <https://github.com/Ovid/Cor>
395
396 The RFC of the new version of OOP planned for the Perl core.
397
398 • MooseX::Modern <https://metacpan.org/pod/MooseX::Modern>
399
400 MooseX::Modern - Precision classes for Modern Perl
401
402 • Zydeco <https://metacpan.org/pod/Zydeco>
403
404 Zydeco - Jazz up your Perl
405
406 • Dios <https://metacpan.org/pod/Dios>
407
408 Dios - Declarative Inside-Out Syntax
409
410 • MooseX::AttributeShortcuts
411 <https://metacpan.org/pod/MooseX::AttributeShortcuts>
412
413 MooseX::AttributeShortcuts - Shorthand for common attribute options
414
416 Curtis "Ovid" Poe <curtis.poe@gmail.com>
417
419 This software is Copyright (c) 2022 by Curtis "Ovid" Poe.
420
421 This is free software, licensed under:
422
423 The Artistic License 2.0 (GPL Compatible)
424
425
426
427perl v5.36.1 2023-06-26 MooseX::Extended(3)