Controlling the start and endings of method calls
Anonymous Monk
created: 2006-02-01 19:27:33
I have several methods that execute the same 2 lines of code at the beginning of their subs. These 2 lines check to see if the methods were called with arguments. If so, an error message is displayed. In other words, these methods don't accept arguments.

What can I do to reduce the repetition of writing those 2 lines for every method? Someone suggested that I use a module to handle the attributes of the methods, but I am hoping to do this without the help of a module.

Also, at the end of certain methods (about a dozen or so), I print some HTML. It is always the same HTML. I was hoping the I could use DESTROY as a means of tacking on that HTML to the method calls that need them. Would that be a good thing to do? Thanks Monks.

Re: Controlling the start and endings of method calls
created: 2006-02-01 19:43:20
What you're looking for is something that for instance [mod://Hook::WrapSub] provides. Other similar modules include [mod://Class::Hook], but there are many more. Searching on "Hook" gives you enough to get, err, dizzy ;)

The documentation for Hook::WrapSub has some suggestions that apply directly to your requirements:

use Hook::WrapSub qw( wrap_subs );

wrap_subs \&before, 'some_func', 'another_func', \&after;

sub before {
    croak "No arguments allowed!" if @_;  

    # but if you're wrapping object methods, you might want to take
    # the object reference (i.e. $self) into account:
    # croak "No arguments allowed" if @_ > 1;
}

sub after {
    print "Always the same ...";
}

# your subs follow
Re: Controlling the start and endings of method calls
created: 2006-02-01 20:41:34

Well, you could reduce it to one line I suppose. This method relies on the fact that if a sub is called with an '&' and without an explicit parameter list, it inherits @_ from its caller (see [doc://perlsub]).

use strict;
use warnings;

package TestClass;

sub has_params {
    return @_ > 1 ? scalar(@_) - 1 : 0;
}


sub mytest {
    die "@_\n" if &has_params;
    print "We're ok.\n";
}

1;

package main;

print "Testing with no parameters.\n\t";
TestClass->mytest( );

print "Testing with one parameter.\n\t";
TestClass->mytest( "Hello" );

There is one trick though, and I'm sure you're already dealing with it somehow: When a sub is called as a method (be it a class method or an object method) it will have one parameter passed into @_; either the class name or the self object ref. That's why in my "has_params()" subroutine, I only trigger a positive if there is more than one parameter.

When you run the snippet above you'll see that it passes the first test, and dies on the second one.


Dave

Re^2: Controlling the start and endings of method calls
created: 2006-02-02 06:06:19
sub _has_params {
    return @_ > 1 ? scalar(@_) - 1 : 0;
}

How 'bout

sub _has_params { @_ - 1 }

?

It would also check if it is called as a sub with no arguments... oh, well, and it wouldn't catch a call like a sub with exactly one argument...

Re^3: Controlling the start and endings of method calls
created: 2006-02-02 11:34:53

But then if the 'method' was invoked as a sub from within the class it could potentially have no params, leading to a return value of -1, which would give a false positive.


Dave

Re^4: Controlling the start and endings of method calls
created: 2006-02-02 13:30:54
Indeed. Just to make sure: I was more brainstorming than stating claims! However this directly leads us to discuss whether it is generally (i.e. with the exclusion of possible corner cases) a good practice to call a method like a sub even from within the same class, which at first sight IMHO is not by any means, but that would bring us too far away and in this moment I'm far too tired to even try to think of it...

perlmonks.org content © perlmonks.org and Anonymous Monk, blazar, davido, rhesa

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03