File: Recipe8.pod

package info (click to toggle)
libmoose-perl 1.09-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 3,004 kB
  • ctags: 1,472
  • sloc: perl: 25,387; makefile: 2
file content (125 lines) | stat: -rw-r--r-- 3,248 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

=pod

=head1 NAME

Moose::Cookbook::Basics::Recipe8 - Builder methods and lazy_build

=head1 SYNOPSIS

  package BinaryTree;
  use Moose;

  has 'node' => (is => 'rw', isa => 'Any');

  has 'parent' => (
      is        => 'rw',
      isa       => 'BinaryTree',
      predicate => 'has_parent',
      weak_ref  => 1,
  );

  has 'left' => (
      is        => 'rw',
      isa       => 'BinaryTree',
      predicate => 'has_left',
      lazy      => 1,
      builder   => '_build_child_tree',
  );

  has 'right' => (
      is        => 'rw',
      isa       => 'BinaryTree',
      predicate => 'has_right',
      lazy      => 1,
      builder   => '_build_child_tree',
  );

  before 'right', 'left' => sub {
      my ($self, $tree) = @_;
      $tree->parent($self) if defined $tree;
  };

  sub _build_child_tree {
      my $self = shift;

      return BinaryTree->new( parent => $self );
  }

=head1 DESCRIPTION

If you've already read L<Moose::Cookbook::Basics::Recipe3>, then this
example should look very familiar. In fact, all we've done here is
replace the attribute's C<default> parameter with a C<builder>.

In this particular case, the C<default> and C<builder> options act in
exactly the same way. When the C<left> or C<right> attribute is read,
Moose calls the builder method to initialize the attribute.

Note that Moose calls the builder method I<on the object which has the
attribute>. Here's an example:

  my $tree = BinaryTree->new();

  my $left = $tree->left();

When C<< $tree->left() >> is called, Moose calls C<<
$tree->_build_child_tree() >> in order to populate the C<left>
attribute. If we had passed C<left> to the original constructor, the
builder would not be called.

There are some differences between C<default> and C<builder>. Notably,
a builder is subclassable, and can be composed from a role. See
L<Moose::Manual::Attributes> for more details.

=head2 The lazy_build shortcut

The C<lazy_build> attribute option can be used as sugar to specify
a whole set of attribute options at once:

  has 'animal' => (
      is         => 'ro',
      isa        => 'Animal',
      lazy_build => 1,
  );

This is a shorthand for:

  has 'animal' => (
      is        => 'ro',
      isa       => 'Animal',
      required  => 1,
      lazy      => 1,
      builder   => '_build_animal',
      predicate => 'has_animal',
      clearer   => 'clear_animal',
  );

If your attribute starts with an underscore, Moose is smart and will
do the right thing with the C<predicate> and C<clearer>, making them
both start with an underscore. The C<builder> method I<always> starts
with an underscore.

You can read more about C<lazy_build> in L<Moose::Manual::Attributes>

=head1 CONCLUSION

The C<builder> option is a more OO-friendly version of the C<default>
functionality. It also separates the default-generating code into a
well-defined method. Sprinkling your attribute definitions with
anonymous subroutines can be quite ugly and hard to follow.

=head1 AUTHOR

Dave Rolsky E<lt>autarch@urth.orgE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright 2006-2010 by Infinity Interactive, Inc.

L<http://www.iinteractive.com>

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut