package Library::OReilly; use Class::Std; { my %book; # Not an attribute hash; shared storage for class sub add_book { my ($class, $title, $book_data) = @_; $book{$title} = $book_data; } # Book titles accumulate throughout the libraries... sub titles :CUMULATIVE { return keys %book; } # Treat every undefined method call as a request for books # with titles containing the method name... sub AUTOMETHOD { # Name of the desired method is passed in $_... my $book_title = $_; # If that name matches any of the book titles, return those titles... if (my @matches = grep { /$book_title/ } keys %book) { return sub{ @book{@matches} }; } # Otherwise fail... return; } } package Library::All; use base qw( Library::OReilly ); { my %book; sub add_book { my ($class, $title, $arg_ref) = @_; $book{$title} = $arg_ref; } sub titles :CUMULATIVE { return keys %book; } sub AUTOMETHOD { my $book_title = $_; if (my @matches = grep { /$book_title/ } keys %book) { return sub{ @book{@matches} }; } return; } } package main; Library::OReilly->add_book( 'Programming Perl' => { ISBN=>596000278, year=>2000 } ); Library::All->add_book( 'Object Oriented Perl' => { ISBN=>1884777791, year=>2000 } ); print join "\n", Library::All->titles(); print "\n-------\n"; use Data::Dumper 'Dumper'; print Dumper(Library::All->Programming()); print "\n-------\n"; print Dumper(Library::All->Python());