File Coverage

blib/lib/Sub/Accessor/Small.pm
Criterion Covered Total %
statement 187 267 70.0
branch 72 156 46.1
condition 21 98 21.4
subroutine 45 53 84.9
pod 0 35 0.0
total 325 609 53.3


line stmt bran cond sub pod time code
1 8     8   70304 use 5.008003;
  8         27  
2 8     8   27 use strict;
  8         12  
  8         145  
3 8     8   29 use warnings;
  8         12  
  8         163  
4 8     8   29 no warnings qw( void once uninitialized );
  8         10  
  8         320  
5              
6              
7             use Carp qw( carp croak );
8 8     8   47 use Eval::TypeTiny qw();
  8         24  
  8         308  
9 8     8   1043 use Exporter::Tiny qw();
  8         4033  
  8         122  
10 8     8   968 use Scalar::Util qw( blessed reftype );
  8         7037  
  8         148  
11 8     8   42  
  8         13  
  8         945  
12             BEGIN {
13             *HAS_SUB_UTIL = eval { require Sub::Util }
14 8         969 ? sub(){1}
15             : sub(){0};
16 8 50   8   30 *HAS_SUB_NAME = !HAS_SUB_UTIL() && eval { require Sub::Name }
17             ? sub(){1}
18             : sub(){0};
19 8 50 33     1081 };
20              
21             BEGIN {
22             *fieldhash =
23             eval { require Hash::FieldHash; \&Hash::FieldHash::fieldhash } ||
24             eval { require Hash::Util::FieldHash; \&Hash::Util::FieldHash::fieldhash } ||
25             do { require Hash::Util::FieldHash::Compat; \&Hash::Util::FieldHash::Compat::fieldhash } ;;
26 8   33 8   20 };
27              
28             our $AUTHORITY = 'cpan:TOBYINK';
29             our $VERSION = '0.014';
30             our @ISA = qw/ Exporter::Tiny /;
31              
32             fieldhash( our %FIELDS );
33              
34             {
35             my $me = shift;
36             my (undef, undef, $export_opts) = @_;
37 8     8   123
38 8         12 my $code = sub
39             {
40             my $attr = $me->new_from_has($export_opts, @_);
41             $attr->install_accessors;
42 24     24   2447 };
        24      
43 24         50
44 8         27 HAS_SUB_UTIL ? ($code = Sub::Util::set_subname("$me\::has", $code)) :
45             HAS_SUB_NAME ? ($code = Sub::Name::subname("$me\::has", $code)) :
46 8         47 ();
47             return $code;
48             }
49 8         18  
50             {
51             my $uniq = 0;
52             {
53             my $me = shift;
54             my $export_opts = ref($_[0]) eq 'HASH' ? shift(@_) : {};
55             my ($name, %opts) = (@_%2) ? @_ : (undef, @_);
56 24     24 0 37
57 24 50       52 my $package;
58 24 50       102 $package = $export_opts->{into}
59             if defined($export_opts->{into}) && !ref($export_opts->{into});
60 24         28
61             $me->new(
62 24 50 33     100 slot => $name,
63             id => $uniq++,
64 24 50       97 _export => $export_opts,
65             ($package ? (package => $package) : ()),
66             %opts,
67             );
68             }
69             }
70              
71             {
72             my $me = shift;
73             my $attr = $me->new_from_has(@_);
74             $attr->install_accessors;
75             }
76 0     0 0 0  
77 0         0 {
78 0         0 my $me = shift;
79             my (%opts) = @_;
80             my $self = bless(\%opts, $me);
81             $self->canonicalize_opts;
82             return $self;
83 24     24 0 31 }
84 24         72  
85 24         43 {
86 24         68 my $me = shift;
87 24         64
88             for my $type (qw( accessor reader writer predicate clearer ))
89             {
90             next unless defined $me->{$type};
91             $me->install_coderef($me->{$type}, $me->$type);
92 24     24 0 28 }
93            
94 24         37 if (defined $me->{handles}) {
95            
96 120 100       202 my $shv_data;
97 44         149 if ($me->{traits} or $me->{handles_via}) {
98            
99             my @pairs = $me->expand_handles;
100 24 100       44 my %handles_map;
101             while ( @pairs ) {
102 1         2 my ( $name ) = splice( @pairs, 0, 2 );
103 1 50 33     4 $handles_map{"$name"} = $name;
104             }
105 1         3
106 1         2 require Sub::HandlesVia::Toolkit::SubAccessorSmall;
107 1         3 my $SHV = 'Sub::HandlesVia::Toolkit::SubAccessorSmall'->new(
108 2         4 attr => $me,
109 2         5 handles_map => \%handles_map,
110             );
111             $shv_data = $SHV->clean_spec(
112 1         303 $me->{package},
113 1         4 $me->{slot},
114             +{%$me},
115             );
116             $shv_data and $SHV->install_delegations( $shv_data );
117             }
118            
119             if (!$shv_data) {
120 1         9 my @pairs = $me->expand_handles;
121             while (@pairs) {
122 1 50       37 my ($target, $method) = splice(@pairs, 0, 2);
123             $me->install_coderef($target, $me->handles($method));
124             }
125 1 50       50 }
126 0         0 }
127 0         0
128 0         0 my @return = map $$_,
129 0         0 $me->{is} eq 'ro' ? ($me->{reader}) :
130             $me->{is} eq 'rw' ? ($me->{accessor}) :
131             $me->{is} eq 'rwp' ? ($me->{reader}, $me->{writer}) :
132             $me->{is} eq 'lazy' ? ($me->{reader}) :
133             ();
134             wantarray ? @return : $return[0];
135             }
136              
137             {
138 24 100       121 my $me = shift;
    100          
    100          
    100          
139             my ($target, $coderef) = @_;
140 24 100       2344
141             return unless defined $target;
142            
143             if (!ref $target and $target =~ /\A[^\W0-9]\w+\z/)
144             {
145 46     46 0 488 my $name = "$me->{package}\::$target";
146 46         72 HAS_SUB_UTIL ? ($coderef = Sub::Util::set_subname($name, $coderef)) :
147             HAS_SUB_NAME ? ($coderef = Sub::Name::subname($name, $coderef)) :
148 46 50       84 ();
149             no strict qw(refs);
150 46 100 66     108 *$name = $coderef;
151             return;
152 3         8 }
153 3         14
154             if (ref($target) eq q(SCALAR) and not defined $$target)
155             {
156 8     8   54 $$target = $coderef;
  8         12  
  8         16858  
157 3         10 return;
158 3         8 }
159            
160             if (!ref($target) and $target eq 1)
161 43 50 33     149 {
162             return;
163 43         47 }
164 43         83
165             croak "Expected installation target to be a reference to an undefined scalar; got $target";
166             }
167 0 0 0     0  
168             {
169 0         0 my $me = shift;
170            
171             if (ref($me->{handles}) eq q(ARRAY))
172 0         0 {
173             return map ($_=>$_), @{$me->{handles}};
174             }
175             elsif (ref($me->{handles}) eq q(HASH))
176             {
177 0     0 0 0 return %{$me->{handles}};
178             }
179 0 0       0
    0          
180             croak "Expected delegations to be a reference to an array or hash; got $me->{handles}";
181 0         0 }
  0         0  
182              
183             {
184             my %one = (
185 0         0 accessor => [qw/ %s %s /],
  0         0  
186             reader => [qw/ get_%s _get%s /],
187             writer => [qw/ set_%s _set%s /],
188 0         0 predicate => [qw/ has_%s _has%s /],
189             clearer => [qw/ clear_%s _clear%s /],
190             trigger => [qw/ _trigger_%s _trigger_%s /],
191             builder => [qw/ _builder_%s _builder_%s /],
192             );
193            
194             {
195             my $me = shift;
196            
197             my $is_private = ($me->{slot} =~ /\A_/) ? 1 : 0;
198            
199             for my $type (keys %one)
200             {
201             next if !exists($me->{$type});
202             next if ref($me->{$type});
203             next if $me->{$type} ne 1;
204 24     24 0 29
205             croak("Cannot interpret $type=>1 because attribute has no name defined")
206 24 50       66 if !defined $me->{slot};
207            
208 24         63 $me->{$type} = sprintf($one{$type}[$is_private], $me->{slot});
209             }
210 168 100       264 }
211 48 100       81
212 2 50       4 {
213             my $me = shift;
214             my $name = $me->{slot};
215 0 0       0
216             if (ref $me->{builder} eq 'CODE')
217 0         0 {
218             HAS_SUB_UTIL or
219             HAS_SUB_NAME or
220             do { require Sub::Util };
221            
222             my $code = $me->{builder};
223 24     24 0 31 defined($name) && defined($me->{package})
224 24         36 or croak("Invalid builder; expected method name as string");
225            
226 24 50       46 my $is_private = ($name =~ /\A_/) ? 1 : 0;
227            
228             my $subname = sprintf($one{builder}[$is_private], $name);
229             my $fq_subname = "$me->{package}\::$name";
230 0         0 $me->_exporter_install_sub(
231             $subname,
232 0         0 {},
233             $me->{_export},
234 0 0 0     0 Sub::Name::subname($fq_subname, $code),
235             );
236 0 0       0 }
237             }
238 0         0 }
239 0         0  
240             {
241             my $me = shift;
242             my $name = $me->{slot};
243            
244 0         0 if ($me->{is} eq 'rw')
245             {
246             $me->{accessor} = $name
247             if !exists($me->{accessor}) and defined $name;
248             }
249             elsif ($me->{is} eq 'ro')
250             {
251             $me->{reader} = $name
252 2     2 0 3 if !exists($me->{reader}) and defined $name;
253 2         2 }
254             elsif ($me->{is} eq 'rwp')
255 2 50       7 {
    50          
    50          
    50          
256             $me->{reader} = $name
257             if !exists($me->{reader}) and defined $name;
258 0 0 0     0 $me->{writer} = "_set_$name"
259             if !exists($me->{writer}) and defined $name;
260             }
261             elsif ($me->{is} eq 'lazy')
262             {
263 0 0 0     0 $me->{reader} = $name
264             if !exists($me->{reader}) and defined $name;
265             $me->{lazy} = 1
266             if !exists($me->{lazy});
267             $me->{builder} = 1
268 0 0 0     0 unless $me->{builder} || $me->{default};
269             }
270 0 0 0     0 }
271              
272             {
273             my $me = shift;
274             return unless exists $me->{default};
275 0 0 0     0
276             unless (ref $me->{default})
277 0 0       0 {
278             my $value = $me->{default};
279 0 0 0     0 $me->{default} = sub { $value };
280             }
281            
282             croak("Invalid default; expected a CODE ref")
283             unless ref $me->{default} eq 'CODE';
284             }
285 24     24 0 28  
286 24 100       41 {
287             my $me = shift;
288 5 50       13
289             if (my $does = $me->{does})
290 0         0 {
291 0     0   0 $me->{isa} ||= sub { blessed($_[0]) && $_[0]->DOES($does) };
  0         0  
292             }
293            
294             if (defined $me->{isa} and not ref $me->{isa})
295 5 50       13 {
296             my $type_name = $me->{isa};
297             eval { require Type::Utils }
298             or croak("Missing requirement; type constraint strings require Type::Utils");
299            
300 24     24 0 27 $me->{isa} = $me->{package}
301             ? Type::Utils::dwim_type($type_name, for => $me->{package})
302 24 50       43 : Type::Utils::dwim_type($type_name);
303             }
304 0 0 0 0   0 }
  0         0  
305              
306             {
307 24 50 66     58 my $me = shift;
308            
309 0         0 if (defined $me->{trigger} and not ref $me->{trigger})
310 0 0       0 {
  0         0  
311             my $method_name = $me->{trigger};
312             $me->{trigger} = sub { my $self = shift; $self->$method_name(@_) };
313             }
314             }
315 0 0       0  
316             {
317             my $me = shift;
318            
319             croak("Initializers are not supported") if $me->{initializer};
320             croak("Traits are not supported") if $me->{traits};
321 24     24 0 28 croak("The lazy_build option is not supported") if $me->{lazy_build};
322            
323 24 50 66     66 $me->canonicalize_1;
324             $me->canonicalize_is;
325 0         0 $me->canonicalize_isa;
326 0     0   0 $me->canonicalize_default;
  0         0  
  0         0  
327             $me->canonicalize_builder;
328             $me->canonicalize_trigger;
329             }
330              
331             {
332 24     24 0 28 return 'small';
333             }
334 24 50       67  
335 24 50       48 {
336 24 50       39 my $me = shift;
337             my ($method_type, $code) = @_;
338 24         62  
339 24         209 my $kind = $me->accessor_kind;
340 24         64 my $src = sprintf(q[sub { %s }], $code);
341 24         62 my $desc = defined($me->{slot})
342 24         51 ? sprintf('%s %s for %s', $kind, $method_type, $me->{slot})
343 24         40 : sprintf('%s %s', $kind, $method_type);
344             # warn "#### $desc\n$src\n";
345            
346             return Eval::TypeTiny::eval_closure(
347             source => $src,
348 2     2 0 3 environment => $me->{inline_environment},
349             description => $desc,
350             );
351             }
352              
353 46     46 0 49 {
354 46         57 my $me = shift;
355            
356 46         69 $me->inline_to_coderef(
357 46         84 clearer => $me->inline_clearer,
358             );
359             }
360 46 50       128  
361             {
362             my $me = shift;
363            
364             sprintf(
365             q[ delete(%s) ],
366 46         117 $me->inline_access,
367             );
368             }
369              
370             {
371             my $me = shift;
372 4     4 0 7
373             sprintf(
374 4         14 q[ $Sub::Accessor::Small::FIELDS{$_[0]}{%d} ],
375             $me->{id},
376             );
377             }
378              
379             {
380             my $me = shift;
381 4     4 0 6 my ($expr) = @_;
382            
383 4         8 sprintf(
384             q[ %s = %s ],
385             $me->inline_access,
386             $expr,
387             );
388             }
389              
390             {
391 88     88 0 96 my $me = shift;
392            
393             $me->inline_to_coderef(
394             predicate => $me->inline_predicate,
395             );
396 88         314 }
397              
398             {
399             my $me = shift;
400            
401 26     26 0 50 sprintf(
402 26         38 q[ exists(%s) ],
403             $me->inline_access,
404 26         49 );
405             }
406              
407             {
408             my $me = shift;
409             my ($method) = @_;
410            
411             $me->inline_to_coderef(
412             'delegated method' => $me->inline_handles,
413 4     4 0 7 );
414             }
415 4         14  
416             my $handler_uniq = 0;
417             {
418             my $me = shift;
419             my ($method) = @_;
420            
421             my $get = $me->inline_access;
422 9     9 0 12
423             my $varname = sprintf('$handler_%d', ++$handler_uniq);
424 9         14 $me->{inline_environment}{$varname} = \($method);
425            
426             my $death = 'Scalar::Util::blessed($h) or Carp::croak("Expected blessed object to delegate to; got $h")';
427            
428             if (ref $method eq 'ARRAY')
429             {
430             return sprintf(
431             q[ %s; my $h = %s; %s; shift; my ($m, @a) = @%s; $h->$m(@a, @_) ],
432 0     0 0 0 $me->inline_default,
433 0         0 $get,
434             $death,
435 0         0 $varname,
436             );
437             }
438             else
439             {
440             return sprintf(
441             q[ %s; my $h = %s; %s; shift; $h->%s(@_) ],
442             $me->inline_default,
443 0     0 0 0 $get,
444 0         0 $death,
445             $varname,
446 0         0 );
447             }
448 0         0 }
449 0         0  
450             {
451 0         0 my $me = shift;
452            
453 0 0       0 my $get = $me->inline_access;
454            
455 0         0 if ($me->{auto_deref})
456             {
457             $get = sprintf(
458             q[ do { my $x = %s; wantarray ? (ref($x) eq 'ARRAY' ? @$x : ref($x) eq 'HASH' ? %$x : $x ) : $x } ],
459             $get,
460             );
461             }
462            
463             return $get;
464             }
465 0         0  
466             {
467             my $me = shift;
468            
469             if ($me->{lazy})
470             {
471             my $get = $me->inline_access;
472            
473             if ($me->{default})
474             {
475             $me->{inline_environment}{'$default'} = \($me->{default});
476            
477 29     29 0 54 return sprintf(
478             q[ %s unless %s; ],
479 29         37 $me->inline_access_w( q[$default->($_[0])] ),
480             $me->inline_predicate,
481 29 50       63 );
482             }
483 0         0 elsif (defined $me->{builder})
484             {
485             return sprintf(
486             q[ %s unless %s; ],
487             $me->inline_access_w( q($_[0]->) . $me->{builder} ),
488             $me->inline_predicate,
489 29         116 );
490             }
491             }
492            
493             return '';
494 22     22 0 27 }
495              
496 22 100       38 {
497             my $me = shift;
498 5         10
499             $me->inline_to_coderef(
500 5 50       14 reader => $me->inline_reader,
    0          
501             );
502 5         12 }
503              
504 5         11 {
505             my $me = shift;
506            
507             join('',
508             $me->inline_default,
509             $me->inline_get,
510             );
511             }
512              
513             {
514 0         0 my $me = shift;
515            
516             $me->inline_to_coderef(
517             writer => $me->inline_writer,
518             );
519             }
520 17         78  
521             {
522             my $me = shift;
523            
524             my $get = $me->inline_access;
525 17     17 0 22 my $coerce = $me->inline_type_coercion('$_[1]');
526            
527 17         28 if ($coerce eq '$_[1]') # i.e. no coercion
528             {
529             if (!$me->{trigger} and !$me->{weak_ref})
530             {
531             return $me->inline_access_w(
532             $me->inline_type_assertion('$_[1]'),
533             );
534 22     22 0 52 }
535            
536 22         48 return sprintf(
537             '%s; %s; %s; %s; %s',
538             $me->inline_type_assertion('$_[1]'),
539             $me->inline_trigger('$_[1]', $get),
540             $me->inline_access_w('$_[1]'),
541             $me->inline_weaken,
542             $me->inline_get,
543             );
544 9     9 0 14 }
545            
546 9         24 sprintf(
547             'my $val = %s; %s; %s; %s; %s; $val',
548             $coerce,
549             $me->inline_type_assertion('$val'),
550             $me->inline_trigger('$val', $get),
551             $me->inline_access_w('$val'),
552             $me->inline_weaken,
553 9     9 0 12 );
554             }
555 9         17  
556 9         18 {
557             my $me = shift;
558 9 100       638
559             $me->inline_to_coderef(
560 5 50 33     23 accessor => $me->inline_accessor,
561             );
562 5         14 }
563              
564             {
565             my $me = shift;
566              
567 0         0 my $get = $me->inline_access;
568             my $coerce = $me->inline_type_coercion('$_[1]');
569            
570             if ($coerce eq '$_[1]') # i.e. no coercion
571             {
572             if (!$me->{lazy} and !$me->{trigger} and !$me->{weak_ref})
573             {
574             return sprintf(
575             '(@_ > 1) ? (%s) : %s',
576             $me->inline_access_w( $me->inline_type_assertion('$_[1]') ),
577             $me->inline_get,
578 4         11 );
579             }
580            
581             return sprintf(
582             'if (@_ > 1) { %s; %s; %s; %s }; %s',
583             $me->inline_type_assertion('$_[1]'),
584             $me->inline_trigger('$_[1]', $get),
585             $me->inline_access_w('$_[1]'),
586             $me->inline_weaken,
587             $me->inline_reader,
588             );
589 12     12 0 16 }
590            
591 12         32 sprintf(
592             'if (@_ > 1) { my $val = %s; %s; %s; %s; %s }; %s',
593             $coerce,
594             $me->inline_type_assertion('$val'),
595             $me->inline_trigger('$val', $get),
596             $me->inline_access_w('$val'),
597             $me->inline_weaken,
598 12     12 0 16 $me->inline_reader,
599             );
600 12         49 }
601 12         38  
602             {
603 12 100       730 my $me = shift;
604             my ($var) = @_;
605 8 50 66     48
      33        
606             my $coercion = $me->{coerce} or return $var;
607 7         17
608             unless (ref $coercion)
609             {
610             my $type = $me->{isa};
611            
612             if (blessed($type) and $type->can('coercion'))
613             {
614 1         5 $coercion = $type->coercion;
615             }
616             elsif (blessed($type) and $type->can('coerce'))
617             {
618             $coercion = sub { $type->coerce(@_) };
619             }
620             else
621             {
622             croak("Invalid coerce; type constraint cannot be probed for coercion");
623             }
624            
625 4         34 unless (ref $coercion)
626             {
627             carp("Invalid coerce; type constraint has no coercion");
628             return $var;
629             }
630             }
631            
632             if ( blessed($coercion)
633             and $coercion->can('can_be_inlined')
634             and $coercion->can_be_inlined
635             and $coercion->can('inline_coercion') )
636             {
637 21     21 0 24 return $coercion->inline_coercion($var);
638 21         30 }
639            
640 21 100       60 # Otherwise need to close over $coerce
641             $me->{inline_environment}{'$coercion'} = \$coercion;
642 8 50       24
643             if ( blessed($coercion)
644 8         12 and $coercion->can('coerce') )
645             {
646 8 50 33     54 return sprintf('$coercion->coerce(%s)', $var);
    0 0        
647             }
648 8         74
649             return sprintf('$coercion->(%s)', $var);
650             }
651              
652 0     0   0 {
  0         0  
653             my $me = shift;
654             my ($var) = @_;
655            
656 0         0 my $type = $me->{isa} or return $var;
657            
658             if ( blessed($type)
659 8 50       56 and $type->isa('Type::Tiny')
660             and $type->can_be_inlined )
661 0         0 {
662 0         0 my $ass = $type->inline_assert($var);
663             if ($ass =~ /\Ado \{(.+)\};\z/sm)
664             {
665             return "do { $1 }"; # i.e. drop trailing ";"
666 8 50 33     31 }
      33        
      33        
667             # otherwise protect expression from trailing ";"
668             return "do { $ass }"
669             }
670            
671 8         566 # Otherwise need to close over $type
672             $me->{inline_environment}{'$type'} = \$type;
673            
674             # non-Type::Tiny but still supports inlining
675 0         0 if ( blessed($type)
676             and $type->can('can_be_inlined')
677 0 0 0     0 and $type->can_be_inlined )
678             {
679             my $inliner = $type->can('inline_check') || $type->can('_inline_check');
680 0         0 if ($inliner)
681             {
682             return sprintf('do { %s } ? %s : Carp::croak($type->get_message(%s))', $type->$inliner($var), $var, $var);
683 0         0 }
684             }
685            
686             if ( blessed($type)
687             and $type->can('check')
688 21     21 0 29 and $type->can('get_message') )
689 21         30 {
690             return sprintf('$type->check(%s) ? %s : Carp::croak($type->get_message(%s))', $var, $var, $var);
691 21 100       96 }
692            
693 10 50 33     107 return sprintf('$type->(%s) ? %s : Carp::croak("Value %s failed type constraint check")', $var, $var, $var);
      33        
694             }
695              
696             {
697 10         274 my $me = shift;
698 10 50       886
699             return '' unless $me->{weak_ref};
700 10         69
701             sprintf(
702             q[ Scalar::Util::weaken(%s) if ref(%s) ],
703 0         0 $me->inline_access,
704             $me->inline_access,
705             );
706             }
707 0         0  
708             {
709             my $me = shift;
710 0 0 0     0 my ($new, $old) = @_;
      0        
711            
712             my $trigger = $me->{trigger} or return '';
713            
714 0   0     0 $me->{inline_environment}{'$trigger'} = \$trigger;
715 0 0       0 return sprintf('$trigger->($_[0], %s, %s)', $new, $old);
716             }
717 0         0  
718             1;
719              
720              
721 0 0 0     0 =pod
      0        
722              
723             =encoding utf-8
724              
725 0         0 =for stopwords benchmarking
726              
727             =head1 NAME
728 0         0  
729             Sub::Accessor::Small - small toolkit for generating getter/setter methods
730              
731             =head1 SYNOPSIS
732              
733 9     9 0 40 package MyClass;
734             use Sub::Accessor::Small;
735 9 50       61 use Types::Standard qw( Int );
736            
737 0         0 sub new {
738             my $class = shift;
739             my $self = bless \$class, $class;
740             my %args = @_ == 1 ? %{ $_[0] } : @_;
741            
742             # Simple way to initialize each attribute
743             for my $key ( sort keys %args ) {
744             $self->$key( $args{$key} );
745             }
746 9     9 0 15
747 9         22 return $self;
748             }
749 9 100       30
750             'Sub::Accessor::Small'->new(
751 8         16 package => __PACKAGE__,
752 8         37 name => "foo",
753             is => "rw",
754             isa => Int,
755             )->install_accessors();
756            
757             package main;
758            
759             my $obj = MyClass->new( foo => 42 );
760              
761             =head1 DESCRIPTION
762              
763             This is a small toolkit for generating Moose-like attribute accessors.
764             B<< It does not generate a constructor. >>
765              
766             It stores attribute values inside-out, but it is designed for
767             Sub::Accessor::Small to be subclassed, making it easy to store attributes
768             in other ways.
769              
770             =head1 BUGS
771              
772             Please report any bugs to
773             L<http://rt.cpan.org/Dist/Display.html?Queue=Lexical-Accessor>.
774              
775             =head1 SEE ALSO
776              
777             L<Lexical::Accessor>.
778              
779             =head1 AUTHOR
780              
781             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
782              
783             =head1 COPYRIGHT AND LICENCE
784              
785             This software is copyright (c) 2013-2014, 2017, 2020 by Toby Inkster.
786              
787             This is free software; you can redistribute it and/or modify it under
788             the same terms as the Perl 5 programming language system itself.
789              
790             =head1 DISCLAIMER OF WARRANTIES
791              
792             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
793             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
794             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
795