Subject: | "Foo|Bar" always creates a new type - please warn in the docs that this can appear to leak memory |
I was using MooseX::Types together with MooseX::Params::Validate, like this:
sub foo {
my ($self,%args) = validated_hash(
\@_,
from => { isa => Num|Undef, optional => 1, },
to => { isa => Num|Undef, optional => 1, },
value => { isa => Any, },
);
...
}
Did you know that this leaks memory? For each invocation of the sub,
it's going to create 2 new Moose::Meta::TypeConstraint::Union objects
(due to the invocation of the overloaded '|' in
MooseX::Types::TypeDecorator).
Now, after having spend two days tracking down the leak, I know why it
does, and I've done something like:
my @foo_spec = (
from => { isa => Num|Undef, optional => 1, },
to => { isa => Num|Undef, optional => 1, },
value => { isa => Any, },
);
sub foo {
my ($self,%args) = validated_hash(
\@_, @foo_spec
);
...
}
A warning somewhere in the docs would probably have saved me some
time… could we add to the CAVEATS section something along the lines
of:
Every invocation of the overloaded C<|> operator (like in
C<Str|ArrayRef>) will generate a new type constraint. If you have
such expressions in places that will get invoked more than once in
the life of the process, you probably want to declare a C<subtype>
(like C<subtype StrOrArrayRef, as Str|ArrayRef>) and always use that
one instead.
On the other hand, some memoization of Moose::Meta::TypeConstraint::*
might not be a bad idea…
Thanks.