Search code examples
perlmoo

Moo, lazy attributes, and default/coerce invocation


My Moo based class has both lazy & non-lazy attributes which have both default and coerce subs. If I don't initialize the attributes I'm finding that both default and coerce subs are called for the normal attribute, but only default is called for the lazy attribute. That seems inconsistent. Here's sample code:

package Foo;
use Moo;

has nrml => ( is => 'ro',
              default => sub { print "nrml default\n" },
              coerce  => sub { print "nrml coerce\n" } 
            );

has lazy => ( is => 'ro',
              lazy => 1,
              default => sub { print "lazy default\n" },
              coerce  => sub { print "lazy coerce\n" }
            );



my $q = Foo->new( );

$q->lazy;

The output is:

nrml default
nrml coerce
lazy default

I only expect coerce to run if I provide a value in the constructor. More importantly I expect the same sequence of execution (either default or default and coerce) from both lazy and normal attributes.

So, are my expectations off, is this a bug, or what? Thanks!


Solution

  • Current status: fix shipped in 009014

    One of those two is a bug.

    In fact, thinking about it, one could argue either way about whether coercions -should- be fired on defaults but since Moose does do so, and since coercions are structural (unlike type checks, which are often used for assertion-like things and should always pass except in the presence of a bug), I think it falls that way.

    ... in fact, the problem is that Method::Generate::Accessor when it fires _use_default always wraps it in _generate_simple_set, when it's _generate_set that provides the isa+coerce+trigger wrapping - and I'm fairly sure that Moose fires all three when it's applying a default, so we need to too.

    It's not an entirely trivial fix to make though, because I didn't parameterise _generate_set to take a value indicating how to generate the value to set. I'll try and sort it out tomorrow since I'm planning to cut a release then.

    If you want support for Moo from the developers, please contact [email protected] or join #web-simple on irc.perl.org - it's sheer luck that somebody on the IRC channel saw this question and asked about it :)