[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