[Raleigh-talk] Messing around with symbol tables

Paul Bennett paul.w.bennett at gmail.com
Tue Dec 1 13:53:00 PST 2009


Suppose I have a module. That module takes objects with a cmp() method  
(which behaves like the cmp or <=> operators), and deals with objects in a  
sort order based on the results of $object1->cmp($object2). The objects  
that it deals with also have a clone() method, which creates another  
object with the same contents. I do not have, nor can I have, any other  
assumptions about the objects being dealt with. Of course, to add to the  
fun, the sorting is done piecemeal and on-demand rather than with the  
"sort" keyword, and more to the point, also by somebody else's code (whose  
API requires the method be named exactly "cmp()").

Suppose I have the following utility module, which is supposed to help me  
handle those objects in both forward-sorting and reverse-sorting orders.  
The idea is that the "antiobject" of $foo is identical in all respects to  
$foo (with a reversible transformation of the class name), except a list  
of antiobjects sorts in reverse order ...

package Antiobject;

use strict;
use warnings;

use Carp qw( confess );
use Export qw( import );
use Scalar::Util qw( blessed );

our @EXPORT = qw( antiobject );

sub antiobject {
     my $object = shift;
     my $orig = blessed($object) or confess('Not a blessed object');
     confess('Object cannot cmp()')   unless UNIVERSAL::can($orig, 'cmp');
     confess('Object cannot clone()') unless UNIVERSAL::can($orig, 'clone');
     my $new  = $orig . '::anticlass';
     {
         no strict qw( refs );
         if (!keys %{$new.'::'}) {
             %{$new.'::'} = %{$orig.'::'};
             ${$new.'::'}->{'cmp'} = sub { -(${$orig.'::'}->{'cmp'}->(@_))  
};
         }
     }
     return bless $object->clone() => $new;
}

1;

__END__

This is 100% untested, but I fear in advance that it may be breaking a few  
laws of Perl and/or nature, or at the very least be working on a  
dangerously wrong understanding of the nature and temperament of the Perl  
symbol table.

I just don't have enough of the rest of the code together to be able to  
write meaningful test cases for it yet -- I'm kinda writing the rest of it  
on the assumption that I'll end up with *some* kind of antiobject or  
similar construct that I can plug in to my algorithms as needed.

Anything I should be aware of (aside from "DON'T PLAY AROUND IN OTHER  
PEOPLE'S SYMBOL TABLES, YA DUMMY!!!") before I start trying to test &  
debug it?

Most importantly: is there a safer and saner way to go about this that  
does not rely on foreknowledge of the callers intent or the structure of  
their objects?



Thanks,



--
Paul


More information about the Raleigh-talk mailing list