bump copyright date to 2009
[gitmo/Moose.git] / lib / Moose / Cookbook / Basics / Recipe3.pod
CommitLineData
471c4f09 1
2=pod
3
4=head1 NAME
5
021b8139 6Moose::Cookbook::Basics::Recipe3 - A lazy B<BinaryTree> example
471c4f09 7
8=head1 SYNOPSIS
9
10 package BinaryTree;
471c4f09 11 use Moose;
c765b254 12
13 has 'node' => ( is => 'rw', isa => 'Any' );
14
471c4f09 15 has 'parent' => (
8597d950 16 is => 'rw',
c765b254 17 isa => 'BinaryTree',
471c4f09 18 predicate => 'has_parent',
8597d950 19 weak_ref => 1,
471c4f09 20 );
c765b254 21
471c4f09 22 has 'left' => (
c765b254 23 is => 'rw',
24 isa => 'BinaryTree',
25 predicate => 'has_left',
7c6cacb4 26 lazy => 1,
c765b254 27 default => sub { BinaryTree->new( parent => $_[0] ) },
471c4f09 28 );
c765b254 29
471c4f09 30 has 'right' => (
c765b254 31 is => 'rw',
32 isa => 'BinaryTree',
33 predicate => 'has_right',
34 lazy => 1,
35 default => sub { BinaryTree->new( parent => $_[0] ) },
471c4f09 36 );
c765b254 37
471c4f09 38 before 'right', 'left' => sub {
c765b254 39 my ( $self, $tree ) = @_;
40 $tree->parent($self) if defined $tree;
471c4f09 41 };
42
43=head1 DESCRIPTION
44
8597d950 45In this recipe we take a closer look at attributes, and see how
46some of their more advanced features can be used to create fairly
47complex behaviors.
48
49The class in this recipe is a classic binary tree, each node in the
50tree is represented by an instance of the B<BinaryTree> class. Each
4711f5f7 51instance has a C<node> slot to hold an arbitrary value, a C<right>
8597d950 52slot to hold the right node, a C<left> slot to hold the left node,
53and finally a C<parent> slot to hold a reference back up the tree.
54
455ca293 55Now, let's start with the code. Our first attribute is the C<node>
8597d950 56slot, defined as such:
57
c765b254 58 has 'node' => ( is => 'rw', isa => 'Any' );
8597d950 59
455ca293 60If you recall from the previous recipes, this slot will have a read/write
61accessor generated for it, and has a type constraint on it. The new item here is
62the type constraint of C<Any>. C<Any> is the "root" of the
63L<Moose::Util::TypeConstraints> type hierarchy. It means exactly what it says:
64I<any> value passes the constraint. Now, you could just as easily have left out
65the C<isa>, leaving the C<node> slot unconstrained and retaining this
66behavior. But in this case, we are really including the type constraint for the
67benefit of other programmers, not the computer. It makes clear my intent that
68the C<node> attribute can be of any type, and that the class is a polymorphic
69container.
70
71Next, let's move on to the C<parent> slot:
8597d950 72
73 has 'parent' => (
74 is => 'rw',
c765b254 75 isa => 'BinaryTree',
8597d950 76 predicate => 'has_parent',
77 weak_ref => 1,
78 );
79
455ca293 80As you already know, this code tells you that C<parent> gets a read/write
81accessor and is constrained to only accept instances of B<BinaryTree>. You will
82of course remember from the second recipe that the C<BinaryTree> type constraint
83is automatically created for us by Moose.
8597d950 84
455ca293 85The next attribute option is new, though: the C<predicate> option.
86This option creates a method which can be used to check whether
2be55428 87a given slot (in this case C<parent>) has been initialized. In
8597d950 88this case it will create a method called C<has_parent>. Quite simple,
455ca293 89and quite handy too.
8597d950 90
455ca293 91This brings us to our last attribute option, also a new one. Since C<parent> is
92a circular reference (the tree in C<parent> should already have a reference to
93this one, in its C<left> or C<right> node), we want to make sure that it is also
94a weakened reference to avoid memory leaks. The C<weak_ref> attribute option
95will do just that, C<weak_ref> simply takes a boolean value (C<1> or C<0>) and
96then alters the accessor function to weaken the reference to any value stored in
97the C<parent> slot (1).
8597d950 98
455ca293 99Now, onto the C<left> and C<right> attributes. They are essentially identical,
100save for different names, so I will just describe one here:
8597d950 101
102 has 'left' => (
c765b254 103 is => 'rw',
104 isa => 'BinaryTree',
105 predicate => 'has_left',
8597d950 106 lazy => 1,
c765b254 107 default => sub { BinaryTree->new( parent => $_[0] ) },
8597d950 108 );
109
455ca293 110You already know what the C<is>, C<isa> and C<predicate> options do, but now we
111have two new options. These two options are actually linked together, in fact:
112you cannot use the C<lazy> option unless you have set the C<default> option.
113Class creation will fail with an exception (2).
8597d950 114
115Before I go into detail about how C<lazy> works, let me first
116explain how C<default> works, and in particular why it is wrapped
117in a CODE ref.
118
119In the second recipe the B<BankAccount>'s C<balance> slot had a
120default value of C<0>. Since Perl will copy strings and numbers
121by value, this was all we had to say. But for any other item
266fb1a5 122(ARRAY ref, HASH ref, object instance, etc) you would need to
455ca293 123wrap it in a CODE reference, so this:
8597d950 124
c765b254 125 has 'foo' => ( is => 'rw', default => [] );
8597d950 126
455ca293 127is actually illegal in Moose. Instead, what you really want is this:
8597d950 128
c765b254 129 has 'foo' => ( is => 'rw', default => sub { [] } );
8597d950 130
455ca293 131This ensures that each instance of this class will get its own ARRAY ref in the
132C<foo> slot.
8597d950 133
455ca293 134One other feature of the CODE ref version of the C<default> option is that when
135the subroutine is executed (to get the default value), we pass in the instance
136where the slot will be stored. This can come in quite handy at times, as
137illustrated above, with this code:
8597d950 138
c765b254 139 default => sub { BinaryTree->new( parent => $_[0] ) },
e08c54f5 140
455ca293 141The default value being generated is a new C<BinaryTree> instance for the
142C<left> (or C<right>) slot. Here we set up the correct relationship by passing
143the current instance as the C<parent> argument to the constructor.
8597d950 144
145Now, before we go on to the C<lazy> option, I want you to think
146for a moment. When an instance of this class is created, and the
147slots are being initialized, the "normal" behavior would be for
148the C<left> and C<right> slots to be populated with a new instance
149of B<BinaryTree>. In creating that instance of the C<left> or
150C<right> slots, we would need to create new instances to populate
151the C<left> and C<right> slots of I<those> instances. This would
152continue in an I<infinitely recursive spiral of death> until you had
153exhausted all available memory on your machine.
154
155This is, of course, not good :)
156
455ca293 157Which brings us to the C<lazy> attribute option. The C<lazy> option does just
158what it says: it lazily initializes the slot within the instance. This means
159that it waits till absolutely the I<latest> possible moment to populate the
160slot. So if you, the user, store a value in the slot, everything works normally,
161and what you pass in is stored. However, if you I<read> the slot I<before>
162storing a value in it, then at that I<exact> moment (and no sooner), the slot
163will be populated with the value of the C<default> option.
8597d950 164
e08c54f5 165This option is what allows the B<BinaryTree> class to instantiate
166objects without fear of the I<infinitely recursive spiral of death>
167mentioned earlier.
8597d950 168
455ca293 169So, we have described a quite complex set of behaviors here, and not one method
170had to be written. But wait, we aren't quite done yet; the autogenerated
171C<right> and C<left> accessors are not completely correct. They will not install
172the parental relationships that we need. We could write our own accessors, but
173that would require us to implement all those features we got automatically (type
174constraints, lazy initialization, and so on). Instead, we use method modifiers
175again:
c765b254 176
8597d950 177 before 'right', 'left' => sub {
c765b254 178 my ( $self, $tree ) = @_;
179 $tree->parent($self) if defined $tree;
8597d950 180 };
181
455ca293 182This is a C<before> modifier, just like we saw in the second recipe, but with
183two slight differences. First, we are applying this to more than one method at a
184time. Since both the C<left> and C<right> methods need the same feature, it
185makes sense. The second difference is that we are not wrapping an inherited
186method anymore, but instead a method of our own local class. Wrapping local
187methods is no different, the only requirement is that the wrappee be created
188before the wrapper (after all, you cannot wrap something which doesn't exist,
189right?).
8597d950 190
191Now, as with all the other recipes, you can go about using
455ca293 192B<BinaryTree> like any other Perl 5 class. A more detailed example of its
aa670b9c 193usage can be found in F<t/000_recipes/003_recipe.t>.
8597d950 194
195=head1 CONCLUSION
196
197This recipe introduced you to some of the more advanced behavioral
198possibilities of Moose's attribute mechanism. I hope that it has
199opened your mind to the powerful possibilities of Moose. In the next
200recipe we explore how we can create custom subtypes and take
201advantage of the plethora of useful modules out on CPAN with Moose.
e08c54f5 202
8597d950 203=head1 FOOTNOTES
204
205=over 4
206
207=item (1)
208
209Weak references are tricky things, and should be used sparingly
210and appropriately (such as in the case of circular refs). If you
211are not careful, you will have slot values disappear "mysteriously"
212because perls reference counting garbage collector has gone and
213removed the item you are weak-referencing.
214
215In short, don't use them unless you know what you are doing :)
216
217=item (2)
218
219You I<can> use the C<default> option without the C<lazy> option if
220you like, as we showed in the second recipe.
221
ceb8945d 222And actually, you can use C<builder> instead of C<default>. See
021b8139 223L<Moose::Cookbook::Basics::Recipe9> for details.
ceb8945d 224
8597d950 225=back
226
471c4f09 227=head1 AUTHOR
228
229Stevan Little E<lt>stevan@iinteractive.comE<gt>
230
231=head1 COPYRIGHT AND LICENSE
232
2840a3b2 233Copyright 2006-2009 by Infinity Interactive, Inc.
471c4f09 234
235L<http://www.iinteractive.com>
236
237This library is free software; you can redistribute it and/or modify
238it under the same terms as Perl itself.
239
f7522f24 240=cut