Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^2: curried-up moose

by stvn (Monsignor)
on Jan 18, 2009 at 15:25 UTC ( [id://737158]=note: print w/replies, xml ) Need Help??


in reply to Re: curried-up moose
in thread curried-up moose

I think "subclasses" could be the right word, given eyes are a body-part and inherit the 'blood pressure' attribute from the body,

Actually, I would be more inclined to do that relationship with delegation instead of inheritance as i assume blood pressure would be an active changing value of the instance and not a static value of the class. Something like this perhaps:

package CirculatorySystem; use Moose; has 'pressure' => (is => 'ro', isa => 'HashRef[Int]'); package Eyes; use Moose; has 'body' => ( is => 'rw', isa => 'Body', weak_ref => 1, # cycles are bad handles => [qw[ blood_pressure ]] ); package Body; use Moose; has 'circulatory_system' => ( is => 'ro', isa => 'CirculatorySystem', handles => { blood_pressure => 'pressure' } ); has 'eyes' => ( is => 'ro', isa => 'Eyes', trigger => sub { my $self = shift; # must hook up new eyes # to the body ... $self->eyes->body($self); } ); package main; my $nexus_6 = Body->new( eyes => Eyes->new, # i make your eyes! circulatory_system => CirculatorySystem->new( pressure => { systolic => 112, diastolic => 64 } ), ); print $nexus_6->blood_pressure; # is the same as ... print $nexus_6->circulatory_system->pressure; # is the same as ... print $nexus_6->eyes->blood_pressure;
This way when the pressure of the circulatory system changes, it is reflected in the blood_pressure method of all the other body parts.

... so after writing up around 20 lines of candidate has attributes, I saw myself writing another 20 arounds and, as a lazy programmer that I am, I was asking myself if I was missing something,...

I wonder if you are familiar with the array-ref versions of both has and around?

has [qw[ eyes ears nose mouth ]] => (is => 'rw'); around [qw[ eyes ears nose mouth ]] => sub { ... code to make accessor +s return $self here ... }
Of course you can't get very specific in your has definition, but if you are just prototyping it can be a very useful feature and is easily refactored later on. And also remember that the Moose sugar is only just perl functions, so you can just as easily do this:
my @parts = qw[ eyes ears nose mouth ]; has $_ => ( is => 'rw', predicate => "has_$_" ) foreach @parts;
The same also works for before/after/around as well.

-stvn

Replies are listed 'Best First'.
Re^3: curried-up moose
by rodd (Scribe) on Jan 19, 2009 at 02:51 UTC
    Nexus6! LOL! :D

    Thanks for the example. I completely ignored the usage and conceptual power of handles. In fact, handles is a dish I haven't learned to cook. Is there a recipe for it in Moose::Cookbook? Can't find it. Well, in any case the section on handles in the Moose.pm POD is extensive and I'm reading it over as I write this.

    BTW, the POD mentions a tree example built with handles that would become a recipe, but in the binary tree recipe handles are not used at all. Maybe this "build your own Nexus6" could become a recipe for it.

    around [qw eyes ears nose mouth ] => sub { ... code to make accessors return $self here ... }
    I had completely overlooked the existence and possibilities of the array-ref feature in prototyping. That's a great golf tip. Nice. Just one thing, it looks like
        around [qw[eyes ears nose mouth]]
    won't work. It should be just a straight array such as:
        around qw[eyes ears nose mouth]

    Anyway, your example of using handles for delegation will probably answer most of my chaining needs, but I'd still don't get the subtleties of using handles against using MooseX::CurriedHandles --something I'll look into carefully soon.

    Also, defining relationships --from body to eyes and from eyes to body-- seems a little wordy to me. How about this:

    package Body; use Moose; has 'eyes' => ( is=> 'rw', isa=> 'Eyes', metaclass=> 'MooseX::NestedPackage', class=> q{ has 'color'=> (is=> 'rw', default=> 'blue'); } ); package main; my $body=new Body(); ## gets new eyes too print $body->eyes; ## and they're blue $body->eyes(new Eyes(color=>'brown')); $body->eyes->color('green');

    Would this syntax be way left field? The extension looks like this (with some quite ugly eval's there).

    package MooseX::NestedPackage; use Moose; use Moose::Util; extends 'Moose::Meta::Attribute'; has 'class' => (is=> 'ro',isa=> 'Str'); after 'attach_to_class' => sub { my ($attr, $class) = @_; my $name = $attr->name; # 'eyes' my $class_name = $attr->{isa}; # 'Eyes' my $class_code = $attr->class; # all the antlers my $parent = $class->{package}; # 'Body' my $parent_lc = lc($parent); #'body' $attr->{trigger} = sub { my $self = shift; $self->$name->$parent_lc($self); }; my $code = qq{ package $class_name; use Moose; $class_code; has '$parent_lc' => (is=> 'rw',isa=> '$parent',weak_ref=> 1); }; eval $code; $@ && die qq{ $@:\n$code }; ## default is not needed $attr->{default} = sub{ $class_name->new() }; ## cos defaults should go directly in each nested attribute $attr->{lazy} = 0; ## lazy stopped working outside due to a missi +ng default };

    -rodrigo

      In fact, handles is a dish I haven't learned to cook. Is there a recipe for it in Moose::Cookbook? Can't find it.

      Nothing that specifically does "handles" only, but Dave Rolsky (one of the core Moose team) currently is working on a whole new set of Moose docs through a TPF grant, I suspect he will have something nice in there.

      BTW, the POD mentions a tree example built with handles that would become a recipe, but in the binary tree recipe handles are not used at all.

      Yes, that became Forest::Tree instead, specifically the 'parent' attribute in that object.

      Just one thing, it looks like around [qw[eyes ears nose mouth]] won't work. It should be just a straight array such as:  around qw[eyes ears nose mouth

      Sorry, yes that is correct I don't use the feature as often as the has [] one so I mix it up.

      I'd still don't get the subtleties of using handles against using MooseX::CurriedHandles --something I'll look into carefully soon.

      MooseX::CurriedHandles was originally called MooseX::DeepAccessor but it was expanded and renamed. It is an extension to handles which allows you go even deeper down the method chain if you like. The docs are pretty good, especially the INTERFACE section, however it very much helps to understand vanilla handles first.

      RE: MooseX::NestedPackage

      This looks interesting, but I am not sure it gives you all that much more over writing the packages yourself. I am of the opinion that optimizing for less typing is not really a large benefit. This is not to say that all languages should be as verbose as Java or C#, but that for real-world code it is not a true savings over the long term as it almost always needs to be un-golfed in the end. But that is simply my opinion, so take it with a big giant hunk of salt. You might want to take this to the mailing list (moose@perl.org) and see if anyone else has tried this or would be interested in it.

      -stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://737158]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2024-04-20 03:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found