[Raleigh-talk] Messing around with symbol tables

Michael Peters mpeters at plusthree.com
Tue Dec 1 14:04:40 PST 2009


On 12/01/2009 04:53 PM, Paul Bennett wrote:

> package Antiobject;
>
> use strict;
> use warnings;
>
> use Carp qw( confess );
> use Export qw( import );
> use Scalar::Util qw( blessed );
>
> our @EXPORT = qw( antiobject );

Why export this method?

> 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');

You should be calling can() as $orig->can() instead of UNIVERSAL::can().

> my $new = $orig . '::anticlass';

The intent of this isn't perfectly clear. You're creating a new class 
(or blessing the object into a new class) so I'd probably do something like:

   my $new_class = ref $orig . '::anticlass';

> {
> no strict qw( refs );
> if (!keys %{$new.'::'}) {
> %{$new.'::'} = %{$orig.'::'};
> ${$new.'::'}->{'cmp'} = sub { -(${$orig.'::'}->{'cmp'}->(@_)) };
> }
> }
> return bless $object->clone() => $new;
> }

I can't see anything immediately wrong with this as long as you document 
what you're trying to do and wrap it up in a class it should be fine.

> 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?

You're not really playing around with some other symbol table (monkey 
patching), you're messing around with your own. Perl symbol tables are 
mutable for a reason, just don't abuse it.

But a different (and perhaps cleaner) strategy would be too look at 
something like Moose and Roles. So you clone an object and then apply 
the "ReverseCmp" role to it - 
http://search.cpan.org/~flora/Moose-0.93/lib/Moose/Manual/Roles.pod#APPLYING_ROLES

> 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?

I don't think you're assuming too much about the objects. The only 
assumptions I can see are that they are blessed objects that have a 
cmp() and clone() method. That's pretty simple IMO.

But a different (and perhaps cleaner) strategy would be too look at 
something like Moose and Roles. So you clone an object and then apply 
the "ReverseCmp" role to it - 
http://search.cpan.org/~flora/Moose-0.93/lib/Moose/Manual/Roles.pod#APPLYING_ROLES

I don't know if this approach would work though with objects that aren't 
Moose based and it seems you can't really modify the code of the objects 
that you're using. But maybe you can get some ideas from their code.

-- 
Michael Peters
Plus Three, LP


More information about the Raleigh-talk mailing list