[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