File Coverage

blib/lib/Object/Pad/FieldAttr/LazyInit.pm
Criterion Covered Total %
statement 9 10 90.0
branch n/a
condition n/a
subroutine 4 5 80.0
pod n/a
total 13 15 86.6


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2021-2023 -- leonerd@leonerd.org.uk
5              
6             package Object::Pad::FieldAttr::LazyInit 0.06;
7              
8 2     2   199662 use v5.14;
  2         21  
9 2     2   9 use warnings;
  2         5  
  2         47  
10              
11 2     2   514 use Object::Pad 0.66;
  2         8627  
  2         101  
12              
13             require XSLoader;
14             XSLoader::load( __PACKAGE__, our $VERSION );
15              
16             =head1 NAME
17              
18             C - lazily initialise C fields at first read
19              
20             =head1 SYNOPSIS
21              
22             use Object::Pad;
23             use Object::Pad::FieldAttr::LazyInit;
24              
25             class Item {
26             field $uuid :reader :param :LazyInit(_make_uuid);
27              
28             method _make_uuid {
29             require Data::GUID;
30             return Data::GUID->new->as_string;
31             }
32             }
33              
34             =head1 DESCRIPTION
35              
36             This module provides a third-party field attribute for L-based
37             classes, which declares that the field it is attached to has a lazy
38             initialisation method, which will be called the first time the field's value
39             is read from.
40              
41             B The ability for L to take third-party field attributes
42             is still new and highly experimental, and subject to much API change in
43             future. As a result, this module should be considered equally experimental.
44              
45             =head1 FIELD ATTRIBUTES
46              
47             =head2 :LazyInit
48              
49             field $name :LazyInit(NAME) ...;
50              
51             Declares that if the field variable is read from before it has been otherwise
52             initialised, then the named method will be called first to create an initial
53             value for it. Initialisation by either by a C<:param> declaration, explicit
54             assignment into it, or the use of a C<:writer> accessor will set the value for
55             the field and mean the lazy initialiser will not be invoked.
56              
57             After it has been invoked, the value is stored by the field and thereafter it
58             will behave as normal; subsequent reads will return the current value, and the
59             initialiser method will not be invoked again.
60              
61             In order to avoid the possibility of accidental recursion when generating the
62             value, it is recommended that the logic in the lazy initialisation method be
63             as self-contained as possible; ideally not invoking any methods on C<$self>,
64             and only making use of other fields already declared before the field being
65             initialised. By placing the initialiser method immediately after the field
66             declaration, before any other fields, you can reduce the possibility of
67             getting stuck in such a manner.
68              
69             field $field_zero :param;
70              
71             field $field_one :LazyInit(_make_one);
72             method _make_one {
73             # we can safely use $field_zero in here
74             }
75              
76             field $field_two :LazyInit(_make_two);
77             method _make_two {
78             # we can safely use $field_zero and $field_one
79             }
80              
81             =cut
82              
83             sub import
84             {
85 1     1   77 $^H{"Object::Pad::FieldAttr::LazyInit/LazyInit"}++;
86             }
87              
88             sub unimport
89             {
90 0     0     delete $^H{"Object::Pad::FieldAttr::LazyInit/LazyInit"};
91             }
92              
93             =head1 AUTHOR
94              
95             Paul Evans
96              
97             =cut
98              
99             0x55AA;