Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^2: Moose "unions" and inheritance

by PetaMem (Priest)
on Nov 30, 2012 at 11:42 UTC ( [id://1006463]=note: print w/replies, xml ) Need Help??


in reply to Re: Moose "unions" and inheritance
in thread Moose "unions" and inheritance

Thanks a lot for this example. Many lessons learned. :-)

Starting to grok the code, I 1st wondered why the type constraints do not need to be written in a string. It seems use MooseX::Types::Moose is responsible for being able to do that.

I wondered if it will "do the right thing" if confronted with multiple inheritance and added a "JustTesting" class like so
package JustTesting; use strict; use warnings; use Moose; use MooseX::Types::Moose -all; has 'data' => ( is => 'ro', isa => CodeRef, );

and then of course used extends 'KeyAtom', 'JustTesting'; in the ValAtom class definition. A subsequent my $atom4 = ValAtom->new(sub {});

throws an error
Attribute (data) does not pass the type constraint because: Validation + failed for 'ArrayRef|RegexpRef|Str|HashRef' with value CODE(0x25d85c +0) ...

Indicating, that only the 1st one in the inheritance hierarchy gets propagated. So I assume for it to work independent of how many parent classes were passed, one would have to loop over them in _existing_constraint (how?) and buildup the type constraint before returning it.

Thanks also for the +data hint, that somehow fell of my stack. Although I ask myself what happens if a inheriting class uses +data and some parents have 'rw' while others have e.g. 'ro'.

Bye
 PetaMem
    All Perl:   MT, NLP, NLU

Replies are listed 'Best First'.
Re^3: Moose "unions" and inheritance
by tobyink (Canon) on Nov 30, 2012 at 12:06 UTC

    "Starting to grok the code, I 1st wondered why the type constraints do not need to be written in a string. It seems use MooseX::Types::Moose is responsible for being able to do that."

    Moose type constraints are not strings, they are instances of Moose::Meta::TypeConstraint. has (and indeed the Moose::Meta::Attribute class that powers has) just gives you a little sugar allowing you to indicate type constraints as strings. But internally it translates those to type constraint objects.

    MooseX::Types basically gives you functions defined along these lines:

    # It's actually a lot more complex than this, but just # pretend it's this simple... # sub HashRef () { ### empty prototype return Moose::Meta::TypeConstraint->lookup('HashRef'); }

    So that you can use:

    isa => HashRef

    It also plays some fancy tricks overloading bitwise operators so that HashRef | ArrayRef "just works".

    So everything I did in the previous example would work without MooseX::Types; you'd just need to do a bit of work with Moose::Meta::TypeConstraint objects, so it wouldn't look as pretty.

    "Indicating, that only the 1st one in the inheritance hierarchy gets propagated. So I assume for it to work independent of how many parent classes were passed, one would have to loop over them in _existing_constraint (how?) and buildup the type constraint before returning it."

    Multiple inheritance is always going to make things messier. For example, if you're inheriting from classes A and B where:

    package A; has data => (is => 'ro'); package B; has data => (is => 'rw');

    ... what on earth would you expect to happen?!

    In cases like this, I'd want the class that's doing the multi-inheritance to define as much of the data attribute as it can, and rely on its base classes' definitions as little as possible.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Moose type constraints are not strings, they are instances of Moose::Meta::TypeConstraint.
      Sure, I assumed they have semantics beyond 'being a String'. I just meant from the syntactic perspective, Moose::Manual::Types pretty much makes it look like the types are strings. At least
      ... isa => Str | ArrayRef, ...

      doesn't work without MooseX::Types (Bareword "Str" not allowed while "strict subs"...)

      Anyway, I tried to make this inherited union constraints "do what I mean" for multiple inheritance and came up with
      package ValAtom; use strict; use warnings; use 5.10.1; use Moose; use MooseX::Types::Moose -all; extends 'KeyAtom', 'JustTesting'; has '+data' => ( isa => __PACKAGE__->_existing_constraint('data') . ' | ArrayRe +f | HashRef', ); sub _existing_constraint { my ($class, $attr) = @_; return join ' | ', map { $_->meta->find_attribute_by_name($attr)->type_constraint } $class->meta->superclasses; } 1;
      Back to string again - obviously - as I couldn't figure out how to do it otherwise. But this seems to work.

      Bye
       PetaMem
          All Perl:   MT, NLP, NLU

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2024-04-25 09:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found