From: Gyepi SAM <[EMAIL PROTECTED]>
Date: Thu, 31 May 2007 15:22:32 -0400
Hi Alex,
What you're asking is possible, especially since you only asked for
quick and easy and said nothing about elegant ;)
The situation you describe is known as a 'condition' in Lisp, which allows
you to define the catch and handle exceptional conditions in your program,
including *restarting* the offending piece of code (presumably after
changing program state to prevent looping) . . .
Well, the notion of "restarting" also includes such things as "skip the
operation", "suppress the warning", etc. The "try the same thing again"
restarts are mostly intended for use by interactive debuggers, where
looping is not a problem.
The thing I find most impressive about the Common Lisp condition
system is that it allows the signalling (detection) of an error, the
provision of restart/retry code, and the decision of which restart, if
any, to take (handling) to be implemented by three different people
writing at different times and communicating only through software
documentation. See [1] for a general overview of Lisp conditions.
However, since Alex seems to have control over all of the code
involved, there is a simpler approach. The following version of your
"Plort" example uses a callback [2] that closes over the "done:" label
instead of using eval/die:
#! /usr/bin/perl -w
use strict;
use warnings;
use vars qw($callback);
sub Plort {
print "in Plort, calling Foo()\n";
local $callback = sub {
print "In callback.\n";
goto DONE;
};
Foo();
print "in Plort, returned from Foo() [not]\n";
DONE:
print "in Plort, done with Foo()\n";
}
sub Foo {
print "in Foo, calling Error()\n";
Error();
print "in Foo, back from Error, but you'll never see this line";
}
sub Error {
print "in Error, invoking callback.\n";
$callback->();
}
Plort();
Note that this script works in Perl 5.8.1, but not in 5.6, where the
lexical sub is not allowed to "goto" a label that is in the containing
lexical scope. I don't know exactly when this feature was added/bug was
fixed.
Running this produces the following output:
[EMAIL PROTECTED]> perl-condition.pl
in Plort, calling Foo()
in Foo, calling Error()
in Error, invoking callback.
In callback.
in Plort, done with Foo()
[EMAIL PROTECTED]>
Two advantages of this technique spring to mind:
1. It is transparent to eval/die, so it doesn't muck up other error
processing, an unfortunate weakness of resignalling [3]. In particular,
introducing an eval to the internals of Foo can never intercept the
nonlocal exit performed by the callback.
2. The notion of how many levels to exit (the "parent/grandparent"
thing) doesn't have to be hardwired. The Error sub can be called at
arbitrary points within the implementation of Foo, at different levels,
and will still do the right thing in each case.
HTH,
-- Bob Rogers
http://rgrjr.dyndns.org/
[1] Kent M. Pitman, "Condition Handling in the Lisp Language Family",
http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
[2] Need I say what else I could have called it? ;-}
[3] Perl 6 will do this better.
_______________________________________________
Boston-pm mailing list
[email protected]
http://mail.pm.org/mailman/listinfo/boston-pm