At 18:05 22/01/2001 -0500, [EMAIL PROTECTED] wrote:
>the Perl6 RPC "Pseudo-hashes must die!" and

And indeed, they ought to die. Or be reimplemented. Or something, but quite
simply, don't use them. They'll break, they won't dwim, and chances are
they won't play nice with future/past versions of Perl. Forget they even exist.

As Matt says, array based objects are much much better, and do what you
want them to do. You seem to be deterred by the laziness factor. Not so
much of a problem ! You could use enum, but it has constraints on the names
you can use which I don't like. You also probably don't need all that it does.

Following is a small class that I've been using in one of my projects. You
can use it in two ways:

If you are not extending a class that uses an array based object, simply
define the fields and use them:

package MyClass;
BEGIN { use Tessera::Util::Enum qw(FOO BAR BAZ); }

sub new {
  my $class = shift;
  return bless [], $class;
}

sub foo {
  my $self = shift;
  return $self->[FOO]; # fetch what's at index FOO
}

Sounds simple enough right ? The problem with array based objects is that
generally they can't be extended. That is, if you have a subclass of an
array based class it's a pain to add new fields because you never know if
your base class might add new fields, and thus break your index. That's one
reason why hashes are still used so much. With my class, you can do (in
your subclass):

package MyClass::Subclass;
use base MyClass;
use Tessera::Util::Enum;

BEGIN { 
  Tessera::Util::Enum->extend(
                                         class  => 'MyClass',
                                         with  => [qw(
                                                         NEW_FIELD
                                                         OTHER_NEW
                                                       )],
                                           );
}

sub get_new_field {
  my $self = shift;
  return $self->[NEW_FIELD];
}

and it will just work. One thing you can't have is multiple inheritance
(well, you can choose to extend just one of the parent classes). I've been
using this quite extensively in a system of mine, and I've been quite happy
with it. It does reduce memory usage in a DOM2 implementation of mine. Of
course, you can change the class name as it won't mean anything outside my
framework, tweak it, throw it out the window, etc...

Perhaps I should put it on CPAN if there's interest in such things (and no
such module is already there).

###
# Tessera Enum Class
# Robin Berjon <[EMAIL PROTECTED]>
# 03/11/2000 - prototype mark V
###

package Tessera::Util::Enum;
use strict;
no strict 'refs';
use vars qw($VERSION %packages);
$VERSION = '0.01';

#---------------------------------------------------------------------#
# import()
#---------------------------------------------------------------------#
sub import {
    my $class = shift;
    @_ or return;
    my $pkg = caller();

    my $idx = 0;
    for my $enum (@_) {
        *{$pkg . '::' . $enum} = eval "sub () { $idx }";
        $idx++;
    }
    $packages{$pkg} = $idx; # this is the idx of the next field
}
#---------------------------------------------------------------------#


#---------------------------------------------------------------------#
# extend(class => 'class', with => \@ra_fieldnames)
#---------------------------------------------------------------------#
sub extend {
    my $class = shift;
    my %options = @_;
    my $pkg = caller();

    warn "extending a class ($options{class}) that hasn't yet been defined"
        unless $options{class};

    my $idx = $packages{$options{class}};
    for my $enum (@{$options{with}}) {
        *{$pkg . '::' . $enum} = eval "sub () { $idx }";
        $idx++;
    }
    $packages{$pkg} = $idx; # this is the idx of the next field
}
#---------------------------------------------------------------------#



1;
=pod

=head1 NAME

Tessera::Util::Enum - very simple enums

=head1 SYNOPSIS

  use Tessera::Util::Enum qw(
                              _foo_
                              BAR
                              baz_gum
                            );

  or

  use Tessera::Util::Enum ();
  Tessera::Util::Enum->extend(
                              class => 'Some::Class',
                              with  => [qw(
                                            more_foo_
                                            OTHER_BAR
                                       )],
                             );

=head1 DESCRIPTION

This class only exists because enum.pm has restrictions on naming
that I don't like. I also don't need it's entire power.

It also adds the possibility to extend a class that already uses
Enum to define it's fields. We will start at that index.

=head1 AUTHOR

Robin Berjon <[EMAIL PROTECTED]>

This module is licensed under the same terms as Perl itself.

=cut

-- robin b.
As a computer, I find your faith in technology amusing.

Reply via email to