You've just made a Tie::ArrayXYZ module that ties arrays to your little XYZ protocol. It's great, but you need an extra method to your class. But, you can't call the method with the tied array, you have to call it with the object under the tied array. This results in ICKY code like:
tie @array, 'Tie::ArrayXYZ'; tied(@array)->method(@args);
or, if you've been prudent:
$obj = tie @array, 'Tie::ArrayXYZ'; $obj->method(@args);
But this is a primary flaw in the design of a tied class -- the fact that there is an object behind the variable should be hidden. This means that your user should be allowed to use the extra "methods" as regular functions.
method(@array, @args);
But how do you implement that? Well, you'll need to export "method" to the calling package, and prototype it to take the proper type as the first arg, and then do error-checking to make sure the first arg is actually tied, and that the object it is tied to inherits from your class.

Geez. Maybe that's transparent to the user, but what about the poor coder?

Enter my newest creation, which will probably appear on CPAN in the near future. It allows you to define additional methods on your tied objects as though they were ordinary ones, but then it exports them to the caller, and does all of the above, automatically. Watch:

package Tie::ArrayXYZ; use Tie::Functions qw( @ changeXYZ ); # ... sub CHANGEXYZ { my ($obj, $new_xyz) = @_; $obj->{XYZ} = $new_xyz; } 1;
That's all you need to do. Now, your user's code changes from:
use Tie::ArrayXYZ; tie @array, 'Tie::ArrayXYZ', $some_xyz; # ... tied(@array)->CHANGEXYZ($new_xyz);
to
use Tie::ArrayXYZ; tie @array, 'Tie::ArrayXYZ', $some_xyz; # ... changeXYZ(@array,$new_xyz);
Notice anything different? It looks like a regular function call, but here's what changeXYZ() looks like:
sub main::changeXYZ (\@@) { my $arg = shift; my $obj = tied @$arg; Carp::croak( "First arg to main::changeXYZ must be array tied to Tie::ArrayXYZ" ) unless defined($obj) and $obj->isa("Tie::ArrayXYZ"); return $obj->CHANGEXYZ(@_); }
It's dynamically generated. The name of the class, the name of the function, and the fact that we're expecting an array, are all determined from the use Tie::Functions line:
use Tie::Functions VARTYPE, FUNCTIONS;
The variable type ($, @, %, or *) determines the prototype and dereferencing. The functions are the representation of the method names you want the user to see. Currently, they must be case-insensitively identical to the method name, and the method name must be in all caps. This explains the correlation between 'changeXYZ' on the user's side, and 'CHANGEXYZ' on the module's side. The prototype of the function created also has a '@' as the secondary term, meaning that there can be any number of arguments after the required one. There might be plans to offer a more extensible prototyping system to the coder.

I hope this seems useful to someone. Here's the code:

package Tie::Functions; use Carp; my %trans = qw( $ scalar @ array % hash * glob ); sub import { shift; my $type = shift; my $pkg = caller(0); my $ppkg = caller(1); croak "Type must be '\$', '\@', '%', '*', not '$type'." unless $type eq '$' or $type eq '@' or $type eq '%' or $type eq '* +'; eval qq[ sub ${ppkg}::$_ (\\$type\@) { my \$arg = shift; my \$obj = tied $type\$arg; Carp::croak( "First arg to ${ppkg}::$_ must be $trans{$type} tied to $pkg" ) unless defined(\$obj) and \$obj->isa("$pkg"); return \$obj->\U$_\E(\@_); } ] for @_; } 1;

_____________________________________________________
Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;


In reply to Tied variables and functions for them by japhy

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.