adding more tests to the binary tree recipe, and adding the RoleName type constraint
[gitmo/Moose.git] / lib / Moose / Cookbook / Basics / Recipe3.pod
1
2 =pod
3
4 =head1 NAME
5
6 Moose::Cookbook::Basics::Recipe3 - A lazy B<BinaryTree> example
7
8 =head1 SYNOPSIS
9
10   package BinaryTree;
11   use Moose;
12
13   has 'node' => ( is => 'rw', isa => 'Any' );
14
15   has 'parent' => (
16       is        => 'rw',
17       isa       => 'BinaryTree',
18       predicate => 'has_parent',
19       weak_ref  => 1,
20   );
21
22   has 'left' => (
23       is        => 'rw',
24       isa       => 'BinaryTree',
25       predicate => 'has_left',
26       lazy      => 1,
27       default   => sub { BinaryTree->new( parent => $_[0] ) },
28   );
29
30   has 'right' => (
31       is        => 'rw',
32       isa       => 'BinaryTree',
33       predicate => 'has_right',
34       lazy      => 1,
35       default   => sub { BinaryTree->new( parent => $_[0] ) },
36   );
37
38   before 'right', 'left' => sub {
39       my ( $self, $tree ) = @_;
40       if (defined $tree) {
41           confess "You cannot insert a tree which already has a parent"
42               if $tree->has_parent;
43           $tree->parent($self);
44       }
45   };
46
47 =head1 DESCRIPTION
48
49 This recipe shows how various advanced attribute features can be used
50 to create complex and powerful behaviors.
51
52 The example class is a classic binary tree. Each node in the tree is
53 itself an instance of C<BinaryTree>. It has a C<node>, which holds
54 some arbitrary value. It has C<right> and C<left> attributes, which
55 refer to its child trees, and a C<parent>.
56
57 Let's take a look at the C<node> attribute:
58
59   has 'node' => ( is => 'rw', isa => 'Any' );
60
61 Moose generates a read-write accessor for this attribute. The type
62 constraint is C<Any>, which means literally means it can contain
63 anything.
64
65 We could have left out the C<isa> option, but in this case, we are
66 including it for the benefit of other programmers, not the computer.
67
68 Next, let's move on to the C<parent> attribute:
69
70   has 'parent' => (
71       is        => 'rw',
72       isa       => 'BinaryTree',
73       predicate => 'has_parent',
74       weak_ref  => 1,
75   );
76
77 Again, we have a read-write accessor. This time, the C<isa> option
78 says that this attribute must always be an instance of
79 C<BinaryTree>. In the second recipe, we saw that every time we create
80 a Moose-based class, we also get a corresponding class type
81 constraint.
82
83 The C<predicate> option is new. It creates a method which can be used
84 to check whether or not a given attribute has been initialized. In
85 this case, the method is named C<has_parent>.
86
87 This brings us to our last attribute option, C<weak_ref>. Since
88 C<parent> is a circular reference (the tree in C<parent> should
89 already have a reference to this one, in its C<left> or C<right>
90 attribute), we want to make sure that we weaken the reference to avoid
91 memory leaks. If C<weak_ref> is true, it alters the accessor function
92 so that the reference is weakened when it is set.
93
94 Finally, we have the the C<left> and C<right> attributes. They are
95 essentially identical except for their names, so we'll just look at
96 C<left>:
97
98   has 'left' => (
99       is        => 'rw',
100       isa       => 'BinaryTree',
101       predicate => 'has_left',
102       lazy      => 1,
103       default   => sub { BinaryTree->new( parent => $_[0] ) },
104   );
105
106 There are two new options here, C<lazy> and C<default>. These two
107 options are linked, and in fact you cannot have a C<lazy> attribute
108 unless it has a C<default> (or a C<builder>, but we'll cover that
109 later). If you try to make an attribute lazy without a default, class
110 creation will fail with an exception. (2)
111
112 In the second recipe the B<BankAccount>'s C<balance> attribute had a
113 default value of C<0>. Given a non-reference, Perl copies the
114 I<value>. However, given a reference, it does not do a deep clone,
115 instead simply copying the reference. If you just specified a simply
116 reference for a default, Perl would create it once and it would be
117 shared by all objects with that attribute.
118
119 As a workaround, we use an anonymous subroutine to generate a new
120 reference every time the default is called.
121
122   has 'foo' => ( is => 'rw', default => sub { [] } );
123
124 In fact, using a non-subroutine reference as a default is illegal in Moose.
125
126   has 'foo' => ( is => 'rw', default => [] );
127
128 This will blow up, so don't do it.
129
130 You'll notice that we use C<$_[0]> in our default sub. When the
131 default subroutine is executed, it is called as a method on the
132 object.
133
134 In our case, we're making a new C<BinaryTree> object in our default,
135 with the current tree as the parent.
136
137 Normally, when an object is instantiated, any defaults are evaluated
138 immediately. With our C<BinaryTree> class, this would be a big
139 problem! We'd create the first object, which would immediately try to
140 populate its C<left> and C<right> attributes, which would create a new
141 C<BinaryTree>, which would populate I<its> C<left> and C<right>
142 slots. Kaboom!
143
144 By making our C<left> and C<right> attributes C<lazy>, we avoid this
145 problem. If the attribute has a value when it is read, the default is
146 never executed at all.
147
148 We still have one last bit of behavior to add. The autogenerated
149 C<right> and C<left> accessors are not quite correct. When one of
150 these is set, we want to make sure that we update the parent of the
151 C<left> or C<right> attribute's tree.
152
153 We could write our own accessors, but then why use Moose at all?
154 Instead, we use method modifiers:
155
156   before 'right', 'left' => sub {
157       my ( $self, $tree ) = @_;
158       if (defined $tree) {
159           confess "You cannot insert a tree which already has a parent"
160               if $tree->has_parent;
161           $tree->parent($self);
162       }
163   };
164
165 This is a C<before> modifier, just like we saw in the second recipe,
166 but with two slight differences. First, we are applying the modifier
167 to more than one method at a time, because both C<left> and C<right>
168 attributes need the same behavior. The other difference is that we are
169 not wrapping an inherited method, but rather a method from our own
170 local class. Wrapping local methods is no different, the only
171 requirement is that the wrappee must exist before the wrapper is
172 defined (after all, you cannot wrap something which doesn't exist,
173 right?).
174
175 As with all the other recipes, B<BinaryTree> can be used just like any
176 other Perl 5 class. A more detailed example of its usage can be found
177 in F<t/000_recipes/003_recipe.t>.
178
179 =head1 CONCLUSION
180
181 This recipe introduced several of Moose's advanced features. We hope
182 that this inspires you to think of other ways these features can be
183 used to simplify your code.
184
185 =head1 FOOTNOTES
186
187 =over 4
188
189 =item (1)
190
191 Weak references are tricky things, and should be used sparingly and
192 appropriately (such as in the case of circular refs). If you are not
193 careful, attribute values could disappear "mysteriously" because
194 Perl's reference counting garbage collector has gone and removed the
195 item you are weak-referencing.
196
197 In short, don't use them unless you know what you are doing :)
198
199 =item (2)
200
201 You I<can> use the C<default> option without the C<lazy> option if you
202 like, as we showed in the second recipe.
203
204 Also, you can use C<builder> instead of C<default>. See
205 L<Moose::Cookbook::Basics::Recipe9> for details.
206
207 =back
208
209 =head1 AUTHORS
210
211 Stevan Little E<lt>stevan@iinteractive.comE<gt>
212
213 Dave Rolsky E<lt>autarch@urth.orgE<gt>
214
215 =head1 COPYRIGHT AND LICENSE
216
217 Copyright 2006-2009 by Infinity Interactive, Inc.
218
219 L<http://www.iinteractive.com>
220
221 This library is free software; you can redistribute it and/or modify
222 it under the same terms as Perl itself.
223
224 =cut