Peter
Peter

Reputation: 46

Questions about the eponymous meta-object

Just read perltooc where the author explains the eponymous meta-object. I have some questions about it which I haven't found by searching...

1. Hash has to be named as the object, but if the name of the object if something like My::Good::Class, what will be the name for the eponymous hash for it? I tried:

 package My::Good::Class
 our %Class = ( some_data => 1 );
 sub getEpoHash {
   my $class = shift;
   my $var = ref($class) || $class;
   no strict 'refs';
   return \%$var;
 }

in the case I write our %Class ...; - it doesn't work, but if I write %My::Good::Class = ...; - it works. I don't understand it! In this case Class is a hash for My::Good package... or what?!

2. There is in the article example how to create a monadic class by using eponymous meta-object. But all the example are written without using strict! Do I have to insert in each function no strict 'refs' before using $self or there are other ways to rewrite it with using strict?

Here is the example:

package Cosmos;
%Cosmos = ();
# accessor method for "name" attribute
sub name {
    my $self = shift;
    $self->{name} = shift if @_;
    return $self->{name};
}
# read-only accessor method for "birthday" attribute
sub birthday {
    my $self = shift;
    die "can't reset birthday" if @_; # XXX: croak() is better
    return $self->{birthday};
}
# accessor method for "stars" attribute
sub stars {
    my $self = shift;
    $self->{stars} = shift if @_;
    return $self->{stars};
}
# oh my - one of our stars just went out!
sub supernova {
    my $self = shift;
    my $count = $self->stars();
    $self->stars($count - 1) if $count > 0;
}
# constructor/initializer method - fix by reboot
sub bigbang {
    my $self = shift;
    %$self = (
        name => "the world according to tchrist",
        birthday => time(),
        stars => 0,
    );
    return $self; # yes, it's probably a class. SURPRISE!
}
# After the class is compiled, but before any use or require
# returns, we start off the universe with a bang.
__PACKAGE__ -> bigbang();

Upvotes: 0

Views: 110

Answers (2)

Denis Howe
Denis Howe

Reputation: 2411

I was as confused as Peter so I wrote this:

use strict;
use warnings;

sub describe
{
    my ($class) = @_;

    # Ensure class variable hash name contains "::"
    my $cv = $class . ($class !~ /::/ && "::${class}");
    # Convert symbolic ref to "hard" ref
    no strict "refs";
    $cv = \%$cv;
    use strict;
    print "$class ($cv): \"", $cv->{description}, "\"\n\n";
}

package Simple;

# "our" creates a variable in the current package
# so "our %Simple" is the same as "%Simple::Simple".

# our %Simple = (description => "Simple's package is " . __PACKAGE__);
# print "\%Simple at ", \ %Simple, "\n";

%Simple::Simple = (description => "Simple's package is " . __PACKAGE__);
print "\%Simple::Simple at ", \ %Simple::Simple, "\n";

main::describe __PACKAGE__;

package More::Complex;

%More::Complex =
    (description => "More::Complex's package is " . __PACKAGE__);

print "\%More::Complex at ", \ %More::Complex, "\n";

main::describe __PACKAGE__;

What this demonstrates is that, when in package Simple, saying our %Simple = ... actually means the same as %Simple::Simple = ....

The examples in perltooc.html hide this because they never try to refer to %Simple outside its package. Why would you do such a thing you ask? Because, in the real world, you don't duplicate class variable access code in every package but instead they inherit it from some superclass. The superclass code needs to know that the class variable for class Simple is %Simple::Simple, as in my describe (sort-of-)method.

This little hidden wart makes me wonder if it's not simpler to have a fixed name for class variables like %Simple::class_varibles, %More::Complex::class_variables, even though you don't get to look so clever by using the word "eponymous" :-).

Upvotes: 1

Eric Strom
Eric Strom

Reputation: 40152

The current version of perltooc is strict compliant, you are probably looking at an old version.

http://perldoc.perl.org/perltooc.html#The-Eponymous-Meta-Object

Best practices have changed over time, and many old code examples will require a few no strict 'refs' littered about to get them working with strictures.

Regarding the eponymous hash for a package, if you have a package named My::Good::Class and you treat that string as a hash (with strict refs off), you are referring to the %Class hash in the My::Good package.

Upvotes: 2

Related Questions