The attached diff (patch -p1 < lazy_build.patch) adds lazy_build
support, as documented in Moose::Meta::Attribute, with tests.
diff -uwrN /home/rob/.cpan/build/Moo-0.009007-1aslgY/lib/Method/Generate/Accessor.pm ./lib/Method/Generate/Accessor.pm
--- /home/rob/.cpan/build/Moo-0.009007-1aslgY/lib/Method/Generate/Accessor.pm 2011-02-25 08:18:13.000000000 -0800
+++ ./lib/Method/Generate/Accessor.pm 2011-03-16 13:20:46.000000000 -0700
@@ -28,6 +28,40 @@
} elsif ($is ne 'bare') {
die "Unknown is ${is}";
}
+
+ if ($spec->{lazy_build}) {
+ # sanity check
+
+ die "You can not use lazy_build and default for the same attribute ($name)"
+ if exists $spec->{default};
+
+ # According to Moose::Meta::Attribute, lazy_build sets:
+ #
+ # lazy => 1,
+ # builder => _build_foo
+ # predicate => has_foo
+ # clearer => clear_foo
+
+ # If your attribute starts with an underscore, then the clearer
+ # and predicate will as well:
+ #
+ # lazy => 1
+ # builder => _build__foo
+ # predicate => _has_foo
+ # clearer => _clear_foo
+
+ $spec->{lazy} = 1;
+ $spec->{builder} = '_build_'.$name unless $spec->{builder};
+
+ if ($name =~ /^_/) {
+ $spec->{predicate} = '_has'.$name unless $spec->{predicate};
+ $spec->{clearer} = '_clear'.$name unless $spec->{clearer};
+ } else {
+ $spec->{predicate} = 'has_'.$name unless $spec->{predicate};
+ $spec->{clearer} = 'clear_'.$name unless $spec->{clearer};
+ }
+ }
+
my %methods;
if (my $reader = $spec->{reader}) {
if (our $CAN_HAZ_XS && $self->is_simple_get($name, $spec)) {
diff -uwrN /home/rob/.cpan/build/Moo-0.009007-1aslgY/t/accessor-lazy_build.t ./t/accessor-lazy_build.t
--- /home/rob/.cpan/build/Moo-0.009007-1aslgY/t/accessor-lazy_build.t 1969-12-31 16:00:00.000000000 -0800
+++ ./t/accessor-lazy_build.t 2011-03-16 13:16:37.000000000 -0700
@@ -0,0 +1,61 @@
+use strictures 1;
+use Test::More;
+
+{
+ package Foo;
+
+ use Moo;
+
+ has one => (is => 'ro', lazy_build => 1);
+
+ sub _build_one { 3 }
+}
+
+my $foo = Foo->new;
+
+ok(!$foo->has_one, 'empty');
+is($foo->one, 3, 'lazy default');
+ok($foo->has_one, 'not empty now');
+is($foo->clear_one, 3, 'clearer returns value');
+ok(!$foo->has_one, 'clearer empties');
+is($foo->one, 3, 'default re-fired');
+ok($foo->has_one, 'not empty again');
+
+# attribute names that begin with '_'
+
+{
+ package Bar;
+
+ use Moo;
+
+ has _two => (is => 'ro', lazy_build => 1);
+
+ sub _build__two { 3 }
+}
+
+my $bar = Bar->new;
+
+ok(!$bar->_has_two, 'empty');
+is($bar->_two, 3, 'lazy default');
+ok($bar->_has_two, 'not empty now');
+is($bar->_clear_two, 3, 'clearer returns value');
+ok(!$bar->_has_two, 'clearer empties');
+is($bar->_two, 3, 'default re-fired');
+ok($bar->_has_two, 'not empty again');
+
+# sanity check
+
+eval {
+ package Baz;
+
+ use Moo;
+
+ has three => (is => 'ro', lazy_build => 1, default => 1);
+
+ sub _build_three { 3 }
+
+};
+
+ok ($@ =~ /lazy_build and default/, 'catches invalid options');
+
+done_testing;