Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Re^8: Moose and default values

by tobyink (Abbot)
on Feb 20, 2013 at 23:15 UTC ( #1019862=note: print w/replies, xml ) Need Help??

in reply to Re^7: Moose and default values
in thread Moose and default values

With enough hacking you can make anything look declarative!

use v5.14; use strict; use warnings; # Ugly hack code # package MooseX::AttributeShouldIgnoreFalse { BEGIN { $INC{'MooseX/'} = __FILE__ }; use Sub::Exporter -setup => { exports => ['attribute_should_ignore_false'], groups => { default => ['attribute_should_ignore_false'], }, }; sub attribute_should_ignore_false { my @attrs = @_; my $meta = (scalar caller)->meta; $meta->add_around_method_modifier(BUILDARGS => sub { my $orig = shift; my $self = shift; my $parm = $self->$orig(@_); $parm->{$_} || delete $parm->{$_} for @attrs; $parm; }); } } # Lovely declarative code # package Foo { use Moose; use MooseX::AttributeShouldIgnoreFalse; has foo => (is => 'ro', default => 'whatever'); attribute_should_ignore_false 'foo'; } my $value = 'hello'; print Foo->new(foo => $value)->dump; $value = ''; print Foo->new(foo => $value)->dump;
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

Replies are listed 'Best First'.
Re^9: Moose and default values
by morgon (Curate) on Feb 20, 2013 at 23:28 UTC
    Were getting here :-)

    Ideally I would want to declare everything at the attriute-level, e.g.:

    has foo => (is => "ro", default => { value => "whatever", when => "fal +se" });
    Can you do that as well?

    I am not so much interested in the feature itself, but it is interesting to see some examples of Moose-metaprogramming at work...


      In this case what I'd suggest is a custom type constraint.

      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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1019862]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2018-06-25 06:54 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.