[slimpl] First Post! Catch/throw in Perl
Larry Clapp
larry at theclapp.org
Mon Jan 23 14:44:23 CST 2006
Hi, all, and welcome to the slimpl / slim-vim list.
I thought I'd kick of the list with a little code.
This weekend I finally had most of the scaffolding in place to take a
hack at porting slime-eval, but I didn't finish, because slime-eval
uses catch/throw, which Perl doesn't have, at least not as such, so I
wrote one. (I checked CPAN first, and the stuff I found there all
talk about "exceptions", which catch/throw aren't.) Comments welcome.
# This catch/throw differs from Common Lisp's catch/throw in that you
# should use a string or number as the tag, since the tags are
# compared using Perl's eq, the equivalent of CL's string=. Also it
# doesn't throw an error if there's not a valid catch for the throw,
# it just throws it and the program will die with an uncaught
# exception. That'll probably change in the real implementation.
{
my $secret = []; # create a secret value
sub catch ($&) {
my( $tag, $code ) = @_;
my( $res, @res );
my $wantarray = wantarray;
eval {
if ($wantarray) {
@res = &$code();
} else {
$res = &$code();
}
};
# detect exception / throw
if ($@) {
# detect a real throw ...
if (ref( $@ ) eq 'ARRAY'
&& ref( $@->[ 0 ] ) eq 'ARRAY'
&& $@->[ 0 ] == $secret
# ... to current tag
&& $@->[ 1 ] eq $tag)
{
my @thrown_values = @{ $@ };
splice @thrown_values, 0, 2;
if ($wantarray
|| @thrown_values > 1)
{
return @thrown_values;
} else {
return $thrown_values[ 0 ];
}
} else {
# Not a throw, or not to current tag -- propagate it.
die $@;
}
} else {
# no exception -- return appropriate result
return( $wantarray ? @res : $res );
}
}
sub throw {
# give the "this is a throw" password
die [ $secret, @_ ];
}
}
-- Larry
More information about the slimpl
mailing list