Necesito la habilidad de agregar acciones al final de un bloque léxico donde la acción puede morir. Y necesito la excepción para ser arrojado normalmente y poder ser atrapado normalmente.Necesito un final de acción de alcance léxico que pueda morir normalmente
Lamentablemente, Perl excepciones de casos especiales durante DESTROY tanto agregando "(en la limpieza)" al mensaje y haciéndolo imposible de trazar. Por ejemplo:
{
package Guard;
use strict;
use warnings;
sub new {
my $class = shift;
my $code = shift;
return bless $code, $class;
}
sub DESTROY {
my $self = shift;
$self->();
}
}
use Test::More tests => 2;
my $guard_triggered = 0;
ok !eval {
my $guard = Guard->new(
#line 24
sub {
$guard_triggered++;
die "En guarde!"
}
);
1;
}, "the guard died";
is [email protected], "En guarde! at [email protected] line 24\n", "with the right error message";
is $guard_triggered, 1, "the guard worked";
Quiero que pase. En la actualidad, la excepción es totalmente tragada por la evaluación.
Esto es para Test :: Builder2, por lo que no puedo usar nada más que Perl puro.
El problema subyacente es que tengo un código como éste:
{
$self->setup;
$user_code->();
$self->cleanup;
}
que la limpieza debe ocurrir incluso si el $ user_code muere, otro $ auto entra en un estado extraño. Así que hice esto:
{
$self->setup;
my $guard = Guard->new(sub { $self->cleanup });
$user_code->();
}
La complejidad viene porque la limpieza se ejecuta código de usuario arbitrario y se trata de un caso de uso en donde el Código morirá. Espero que esa excepción sea atrapable e inalterada por el guardia.
Estoy evitando envolver todo en bloques eval debido a la forma en que altera la pila.
http://search.cpan.org/~rgarcia/perl-5.10.0-RC2/pod/perlcall.pod#G_KEEPERR explica el mecanismo ''(en limpieza)' ', http: //cpansearch.perl .org/src/JESSE/perl-5.12.2/ext/XS-APItest/t/call.t muestra su uso. todo esto está relacionado con XS, pero tal vez te ayudará a apuntar a ti o a alguien más a una respuesta perl pura. –
@Eric Gracias por la información extra, no sabía de eso. No creo que tenga ninguna forma de llegar a esa bandera sin XS. ¡Seguro sería útil! – Schwern
+1 por hacerme aprender y recordar un par de cosas geniales de Perl como parte de mi intento de respuesta (y me gustaría poder dar +100 por 'Test :: Builder2' :). Creo que puedo haber encontrado una solución posible para usted - vea la respuesta a continuación - por favor critique si no recibí sus requisitos correctamente – DVK