Class::MOP::Class->meta->add_attribute(
Class::MOP::Attribute->new('%:methods' => (
- #reader => 'get_method_map',
- #reader => {
- # # NOTE:
- # # as with the $VERSION and $AUTHORITY above
- # # sometimes we don't/can't store directly
- # # inside the instance, so we need the accessor
- # # to just DWIM
- # 'get_method_map' => sub {
- # my $self = shift;
- # # FIXME:
- # # there is a faster/better way
- # # to do this, I am sure :)
- # return +{
- # map {
- # $_ => $self->method_metaclass->wrap($self->get_package_symbol('&' . $_))
- # } grep {
- # $self->has_package_symbol('&' . $_)
- # } $self->list_all_package_symbols
- # };
- # }
- #},
- #init_arg => '!............( DO NOT DO THIS )............!',
- #default => sub { \undef }
+ reader => {
+ 'get_method_map' => sub {
+ my $self = shift;
+ my $map = $self->{'%:methods'};
+
+ foreach my $symbol ($self->list_all_package_symbols('CODE')) {
+ my $code = $self->get_package_symbol('&' . $symbol);
+
+ next if exists $map->{$symbol} &&
+ $map->{$symbol}->body == $code;
+
+ $map->{$symbol} = $self->method_metaclass->wrap($code);
+ }
+
+ return $map;
+ }
+ },
default => sub { {} }
))
);
my $self = shift;
my $map = $self->{'%:methods'};
- foreach my $symbol (grep { $self->has_package_symbol('&' . $_) } $self->list_all_package_symbols) {
+ foreach my $symbol ($self->list_all_package_symbols('CODE')) {
next if exists $map->{$symbol} &&
$map->{$symbol}->body == $self->get_package_symbol('&' . $symbol);
my ($self, $method_name, $method) = @_;
(defined $method_name && $method_name)
|| confess "You must define a method name";
- # use reftype here to allow for blessed subs ...
my $body;
-
if (blessed($method)) {
-
- $body = $method->body;
-
- ('CODE' eq (reftype($body) || ''))
- || confess "Your code block must be a CODE reference";
-
+ $body = $method->body;
$self->get_method_map->{$method_name} = $method;
}
- else {
-
+ else {
$body = $method;
-
('CODE' eq (reftype($body) || ''))
|| confess "Your code block must be a CODE reference";
-
$self->get_method_map->{$method_name} = $self->method_metaclass->wrap($body);
-
}
my $full_method_name = ($self->name . '::' . $method_name);
|| confess "You must define a method name";
my $body;
-
if (blessed($method)) {
-
$body = $method->body;
-
- ('CODE' eq (reftype($body) || ''))
- || confess "Your code block must be a CODE reference";
-
$self->get_method_map->{$method_name} = $method;
}
else {
-
$body = $method;
-
('CODE' eq (reftype($body) || ''))
|| confess "Your code block must be a CODE reference";
-
$self->get_method_map->{$method_name} = $self->method_metaclass->wrap($body);
-
}
$self->add_package_symbol("&${method_name}" => $body);
}
sub list_all_package_symbols {
- my ($self) = @_;
- return keys %{$self->namespace};
+ my ($self, $type_filter) = @_;
+ return keys %{$self->namespace} unless defined $type_filter;
+ # or we can filter based on
+ # type (SCALAR|ARRAY|HASH|CODE)
+ my $namespace = $self->namespace;
+ return grep { defined(*{$namespace->{$_}}{$type_filter}) } keys %{$namespace};
}
1;
This will attempt to remove the entire typeglob associated with
C<$glob_name> from the package.
-=item B<list_all_package_symbols>
+=item B<list_all_package_symbols (?$type_filter)>
This will list all the glob names associated with the current package.
By inspecting the globs returned you can discern all the variables in
the package.
+By passing a C<$type_filter>, you can limit the list to only those
+which match the filter (either SCALAR, ARRAY, HASH or CODE).
+
=back
=head1 AUTHORS