Using overloaded operators, we could make them work much like built-in arrays. To create a new one, you would write, e.g.:package TypedArray; use Moose; has type => ( is => 'ro', isa => 'Moose::Meta::TypeConstraint', required => 1 ); has elems => ( is => 'ro', isa => ArrayRef, default => sub { [] }, ); sub BUILD { my $self = shift; $self->type->assert_valid($_) for @{$self->elems}; } sub elems_push { my $self = shift; $self->type->assert_valid($_) for @_; push @{$self->elems}, @_; } ... more methods and operator overloads ...
It would be nice to have a shorthand syntax to create them. We could use BUILDARGS to simplify it to:TypedArray->new(type => Int, elems => [4, 8, -7])
but it would be nice to get rid of even the `new`. We could make a function, e.g.:TypedArray->new(Int, 4, 8, -7)
Then we could define a parameterizable type constraint called TypedArrayOf:typedArray Int, 4, 8, -7
Unfortunately, we could not use the class name for the type constraint, because this is not a class constraint, and we do not want to conflict with the class constraint. So I chose a compromise by appending the word 'Of' to the name. Instead of having a single TypedArray class, another option would be to create a new class on the fly for each possible type parameter. We could use a parameterized role to build them, using Class::MOP to generate the new classes on demand. Then TypedArray would become a function, taking a single parameter that is an arrayref with the contained type. E.g.,subtype TypedArrayOf as Parameterizable['TypedArray', 'Moose::Meta::TypeConstraint' +], where { my ($typed_array, $type) = @_; $typed_array->type->is_a_type_of($type) }, message { my ($typed_array, $type) = @_; return "expected TypedArrayOf[$type], found TypedArrayOf[@ +{[$typed_array->type]}]" };
would look up the Int type in a global cache, and if not found, would generate a new TypedArray class, parameterized on Int. That class would constrain all elements to be Ints. This could get expensive if we end up creating a lot of classes. What do folks think of the naming here? Can we be more succinct? More consistent? How can we avoid naming conflicts between 1) the class without a type parameter, 2) the class with a type parameter, 3) a constructor function without a type paramter, 4) a constructor function with a type parameter, 5) the type constraint without a parameter, 6) the type constraint with a parameter. What is the most "Moosey" approach?TypedArray[Int]
In reply to Naming question by QSeep
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |