in reply to Trouble with, or misunderstanding of, Types::Standard ArrayRef[elements] enforcement in Moo

Forget HandlesVia for now and consider this:

my @toppings = ( FishTaco::Topping->new ); my $ft = FishTaco->new( _toppings => \@toppings ); push @toppings, "OHAI";

You can push stuff onto the array without Moo checking that the stuff you're pushing makes any sense. This is because it only checks the array is valid in the constructor and in non-read-only attribute accessors. The exact same happens with Moose.

Moose native traits give you the handles stuff for arrays, and Moose is smart enough to add type checking to push when you do this. MooX::HandlesVia is not quite so smart. (This is partly due to limitations in how Moo works.)

Now try this:

my @toppings = ( FishTaco::Topping->new ); tie @toppings, InstanceOf['FishTaco::Topping']; my $ft = FishTaco->new( _toppings => \@toppings ); push @toppings, "OHAI"; # this should die

Yay?

Now play around with trigger.

  • Comment on Re: Trouble with, or misunderstanding of, Types::Standard ArrayRef[elements] enforcement in Moo
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: Trouble with, or misunderstanding of, Types::Standard ArrayRef[elements] enforcement in Moo
by Your Mother (Archbishop) on May 01, 2019 at 03:43 UTC

    Thanks. I ended up an around add_topping => …; but your suggestions are worth looking at I think and made me remember the types can be checked manually too. Thanks also for the great software.

      In the latest development releases of Types::Standard, you can do this:

      use Types::Standard is_InstanceOf => { of => "FishTaco::Topping", -as +=> "is_Topping" }; is_Topping( $something ); # returns a boolean

      If you've got Type::Tiny::XS installed, this will be an XS function, so pretty darn fast to call. I haven't done a lot of benchmarking on it, but I'd wager a lot faster than a blessed+isa check. If you don't, then it's still not going to be slow.

      (Older versions, you can do something like this for the same effect...

      BEGIN { require Types::Standard; *is_Topping = Types::Standard::InstanceOf->parameterize("FishTaco::T +opping")->compiled_check; };

      Newer versions just provide support for of in the import method.)

        Terrific. By manually I meant this more than isa/blessed

        my $type = InstanceOf['FishTaco::Topping']; … if ( $type->($topping) ) …