Hi.
I was reading RFC 271 and thinking about this pre/post handler thing. Why
instead of having 2 subs, one for pre and other for post condition, and
having to deal with things as strange as $_[-1], why don't we have only one
handler that calls the real sub?
Instead of:
: pre abc { do_pre_handler(@_); }
: post abc { do_post_handler($_[-1]); }
why not make it:
: pre_post_handler abc {
: do_pre_handler(@_); # pre part
: my $result = REAL_SUB::abc(@_);
: do_post_handler($result);
: return $result;
: }
(Of course, the names "pre_post_handler" and "REAL_SUB" are completely
inadequate, what I'm trying to express is the idea here!)
Advantages of this method:
* Better nesting of pre and post handlers. If the sub throws an exception,
even so the handler could catch it, execute its clean-up code and then
re-throw it. (this is not addressed in the RFC).
* Possibility to execute the post handler even if the sub itself wasn't
executed.
* Easier to uninstall pre and post handlers. (I don't know if uninstalling
handlers is an issue, I believe it is. Using two separate subs leaves space
for uninstalling the pre-handler and forgetting to uninstall the
post-handler, or vice-versa, what might lead to unexpected behaviour.)
* No messing with $_[-1]. (Yeah, I really didn't like it !!!) The splice
behaviour also wasn't very clear to me. I believe the samples that use it to
change @_ assume the number of elements of @_ must be the same (???).
Disadvantages:
* The REAL_SUB:: stuff doesn't allow having anonymous subs as pre/post
handlers. I think an improvement would be passing the real sub as the first
parameter to the handler:
: sub abc_handler {
: my $real_abc = shift;
: do_pre_handler(@_); # pre part
: my $result = $real_abc->(@_);
: do_post_handler($result);
: return $result;
: }
: push_handler(\&abc, \&abc_handler);
Or having the real sub reference in an implicit variable (such as $_). I,
personally, stick with the first one, but I list it down here for
completion:
: sub abc_handler {
: do_pre_handler(@_); # pre part
: my $result = $_->(@_);
: do_post_handler($result);
: return $result;
: }
: push_handler(\&abc, \&abc_handler);
Well, what you think of it? Does it have disadvantages I'm not aware of?
Branden