(Anonymous => mistake, I am wu-lee)
Thanks, this seems to do what I want:
#!/usr/bin/perl
use Carp qw(croak);
sub imp { croak shift(), ": oops" }
sub git { local $Carp::CarpLevel = 2; imp @_; }
git "hello";
Gives:
perl -w ./git.pl
hello: oops at ./git.pl line 8
Sub::Uplevel doesn't work because I don't have it installed on my system. I also want to avoid relying on code which won't work in the old versions of perl some web sites still have installed. Is it core on recent versions or is it CPAN?
My main other worry is that $Carp::CarpLevel isn't documented in the Carp manpage, and thus possibly may stop working without warning. I'll have to suck it and see, I spoze.
I thought of rethrowing, but I want the imp routine to be as straightforward to use as possible (it's a constructor implementation, meant to make writing constructors easier, a la my draft documentation:
construct
A generalised constructor for hash- and array-based classes. Given an array
defining the arguments to the constructor of the form:
@CHECKS =
(
arg1 => undef, # a mandatory but unchecked argument
arg2 => 'mumble', # an optional scalar argument, with the defaul
+t
arg3 => \&check_arg3, # a checked argument.
);
-where check_arg3 should expect the object being constructed as its
first argument, and the named arguments supplied to the constructor
supplied in a hashref as the second argument.
(Using an array @CHECKS instead of a hash %CHECKS allows the order
of argument processing to be specified.)
This then allows a constructor to be written in the client class as
sub new { ClassUtils::construct {}, \@CHECKS, @_ }
(to construct a hash based class), or:
sub new { ClassUtils::construct [], \@CHECKS, @_ }
(to construct an array based class).
The resulting class can be constructed like this:
$OBJ = $CLASS->new(arg1 => 1,
arg2 => 'git',
arg3 => $X);
Any other arguments supplied over and above those defined in %CHECKS
are ignored.
Subclasses' constructors can be defined like this:
sub new { ClassUtils::construct SUPER::new(@_), \%CHECKS, @_ }
The superclass's constructor is called first, and the resulting object
passed to ClassUtils::construct, both informing it which type of
object to build, and giving it a partially constructed object to add
to. ClassUtils::construct gets the name of the class to bless the
objects into from its third argument, so the object will be reblessed
into the appropriate class.
There might be holes in this implementation. And perhaps someone's done this better already... Constructive criticism is of course welcome. (ha ha).
Ta, and ta ta |