use Moose::Util::TypeConstraints;
subtype 'TrueStr',
as 'Str',
where { !!$_ };
coerce 'TrueStr', from 'Any', via { $_ || "whatever" };
has foo => (is => "ro", isa => "TrueStr", coerce => 1);
Then any value which is not a TrueStr will be coerced into one via the code $_ || "whatever".
Of course, this also applies to accessors, not just the constructor. (Not a problem for a read-only attribute though!) And also, it means that if you've got a bunch of attributes like this, each with different defaults, you need to define a type constraint for each one.
The alternative - attribute metaprogramming - starts off seeming simple enough, but becomes more complicated when you start thinking about immutability. (Attribute metaprogramming can be a real bitch when it touches on immutability.)
A compromise would be to hook has to automatically build per-attribute type constraints and coecions. I submitted a patch to MooseX::AttributeShortcuts for precisely this feature some months ago, but it was only partly accepted: per-attribute constraints are now supported, but not coercions.
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
|