Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Sunday November 13, 2005
07:13 PM

Overriding 'can'

[ #27562 ]

How annoying. I've been working on Model::World and I have agents working properly. However, this comes back to the problem of verbs (actions). What happens when I call this:

$agent->put($box, $ring);

Agent was originally a subclass of Thing but that meant Agent inherited all the methods. The code was trying to put a box in the agent instead of the ring in the box. Now Agent delegates certain methods to Things to take advantage of a "hasa" relationship (you're the agent and you have a thing which represents you), but now I have a relatively naive AUTOLOAD method (I'll cache these methods in the future):

sub AUTOLOAD {
    my ($proto, $thing, @args) = @_;
    my $pkg = ref $proto || $proto;
    $AUTOLOAD =~ s/${pkg}:://;
    my $method = $AUTOLOAD;
    if ($thing->can($method)) {
        $thing->$method(@args);
        return $proto;
    }
    return;
}

This presents a problem, though. The agent "can" put things, but only in the context of a given thing. Thus, calling $agent->can('put'); doesn't make a lot of sense. For example, you cannot shatter things but if you make a "mirror" class and provide a shatter() method, you can shatter the mirror. However, you can't shatter a box, even though the agent can try to shatter it. Thus, there are two different types of "can". Whether an agent "can" attempt an action and whether or not a Thing "can" receive the action. In comes introspection.

package Model::World::Thing::Mirror;
use base 'Model::World::Thing';

sub shatter : Verb { ... }

The World has a vocabulary. If all "actionable" methods have a Verb attribute, I can add that verb to the vocabulary. Then the agent's can() method looks like this:

sub can {
    my ($self, $action) = @_;
    if ( Vocabulary->has_word( verb => $action ) ) {
        my $sub = sub {
            my ($proto, $thing, @args) = @_;
            if ($thing->can($action)) {
                $thing->$action(@args);
                return $proto;
            }
        };
        no strict 'refs';
        *$action = $sub;
        return $sub;
    }
    return;
}

This allows us to cleanly separate which messages an agent can send to objects and which methods the object can receive (though I'll need to refactor this for the AUTOLOAD method).

Time for me to start rereading the Attribute::Handlers docs.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.