[Dahut-pm] QNames and Loaded Magic

Robin Berjon robin.berjon at expway.fr
Wed Apr 20 05:01:12 PDT 2005


DAHUT!

While chatting with ubu it turned out that there would be interest in 
being able to call $obj->foo:bar(...) where foo:bar is a method that 
corresponds to a QName (for XML, RDF, etc.). Unfortunately, ':' is 
reserved there and can't be used. But other characters, which are 
illegal in NCNames, can be used there with a little trickery.

In this case I picked '^'. It could be '|' or a host of others. The 
former seemed less intrusive, the latter has stronger 'or' connotations 
but has the advantage of being the namespace separator used by CSS.

The code uses a bit of AUTOLOAD and overload. Tell me what you think, is 
that a nice way of hacking qnames into Perl? The code is a bit long but 
almost all of it is meant to be hidden.


# this is the main package
# we use an AUTOLOAD directly but it could have been installed by
# a module being use'd (which could look to see if there is already
# one and give up).
# The idea is that one can call $obj->foo^bar() where foo^bar represents
# the foo:bar QName (mapping to IRIs is left as an exercize to the reader)
# Downsides are that an AUTOLOAD cannot exist, and that the QName must have
# a () even if it doesn't have arguments.

use strict;
use vars qw/$AUTOLOAD/;

my $obj = Object->new;
$obj->foo^bar('dahut', 'Bender');

sub AUTOLOAD {
     my @args = @_;
     my $ln = ($AUTOLOAD =~ /([^:]+)$/)[0];
     return if $ln eq 'DESTROY';
     print "AUTOLOAD main: $ln\n";
     return LocalName->new( name => $ln, args => \@args );
}

# any method on foo, being incomplete (the part before the ^)
# returns a Prefix object. Nothing special.

package Object;
use vars qw/$AUTOLOAD/;
sub new { return bless []; }
sub AUTOLOAD {
     my $self = shift;
     my $pfx = ($AUTOLOAD =~ /([^:]+)$/)[0];
     return if $pfx eq 'DESTROY';
     print "AUTOLOAD: $pfx\n";
     return Prefix->new( prefix => $pfx, object => $self );
}

# LocalName objects deal with the rhs of the ^. They save the
# local name and the arguments so that they can be accessed later.

package LocalName;
sub new {
     shift;
     my %opts = @_;
     return bless \%opts;
}

# Prefix is the lhs of the ^, and it knows both which prefix was
# used and which object it was called on.
# It uses overloading so that the bitwise ^ operator calls
# makeMeth. What the latter does is up to you. This one
# dumps the info to show what you get, which should be enough to
# call a method of your own.

package Prefix;
use overload '^' => \&makeMeth;
use Data::Dumper;
sub new {
     shift;
     my %opts = @_;
     return bless \%opts;
}

sub makeMeth {
     my $pfx = shift;
     my $ln = shift;
     # you figure out what to do here
     print Dumper({ pfx_context => $pfx, ln_params => $ln });
}





-- 
Robin Berjon
   Research Scientist
   Expway, http://expway.com/




More information about the Dahut-pm mailing list