2010-10-29 18 views
20

Update3: Si te gusta esta publicación, por favor no me votes más sino vota la genial respuesta de DVK a continuación.

tengo los siguientes subprogramas:

use warnings; 
#Input 
my @pairs = (
    "fred bill", 
    "hello bye", 
    "hello fred", 
    "foo bar", 
    "fred foo"); 

#calling the subroutine 
my @ccomp = connected_component(@pairs); 

use Data::Dumper; 
print Dumper \@ccomp; 

sub connected_component { 

    my @arr = @_; 
    my %links; 

    foreach my $arrm ( @arr) { 
     my ($x,$y) = split(/\s+/,$arrm);; 
     $links{$x}{$y} = $links{$y}{$x} = 1; 

    } 

    my %marked; # nodes we have already visited 
    my @stack; 

    my @all_ccomp; 

    for my $node (sort keys %links) { 
     next if exists $marked{$node}; 
     @stack =(); 
     connected($node); 
     print "@stack\n"; 
     push @all_ccomp, [@stack]; 
    } 

    sub connected { 
     no warnings 'recursion'; 
     my $node = shift; 
     return if exists $marked{$node}; # Line 43 
     $marked{$node} = 1; 
     push @stack, $node; # Line 45 
     my $children = $links{$node}; # Line 46 
     connected($_) for keys %$children; 
    } 


    return @all_ccomp; 
} 

Pero por qué se da este mensaje:

Variable "%marked" will not stay shared at mycode.pl line 43. 
Variable "@stack" will not stay shared at mycode.pl line 45. 
Variable "%links" will not stay shared at mycode.pl line 46. 

¿Es perjudicial? ¿Error? ¿Cómo puedo arreglar mi código para que se deshaga de ese mensaje?

Update1: puedo actualizar el código que se ejecuta como está con el mensaje de error Actuall

Update2: me trató de modificar el uso de sub como se sugiere DVK. ¡Y funcionó!

use warnings; 
#Input 
my @pairs = (
    "fred bill", 
    "hello bye", 
    "hello fred", 
    "foo bar", 
    "fred foo"); 

#calling the subroutine 
my @ccomp = connected_component(@pairs); 

use Data::Dumper; 
print Dumper \@ccomp; 

sub connected_component { 

    my @arr = @_; 
    my %links; 

    foreach my $arrm ( @arr) { 
     my ($x,$y) = split(/\s+/,$arrm);; 
     $links{$x}{$y} = $links{$y}{$x} = 1; 

    } 

    my %marked; # nodes we have already visited 
    my @stack; 

    my @all_ccomp; 

    my $connected_sub; 
    $connected_sub = sub { 
     no warnings 'recursion'; 
     my $node = shift; 
     return if exists $marked{$node}; 
     $marked{$node} = 1; 
     push @stack, $node; 
     my $children = $links{$node}; 
     &$connected_sub($_) for keys %$children; 
    }; 

    for my $node (sort keys %links) { # Line 43 
     next if exists $marked{$node}; 
     @stack =(); 
     &$connected_sub($node); 
     #print "@stack\n"; 
     push @all_ccomp, [@stack]; # Line 49 
    } 

    return @all_ccomp; 
} 
+0

No hay 280 líneas en sus fragmentos (gracias a Dios). Debe reproducir el problema en su código de ejemplo y proporcionar los informes de los números de línea en función de lo que proporcione. –

Respuesta

50

Según perldoc's perldiag para que el error, el problema es que el sub interno hace referencia a una variable léxica (% marcado) definida en la sub exterior.

la solución es en el tercer párrafo (use sub anónimo):

(Warning; cierre) Un interna (anidada) llamado subrutina hace referencia a un variable de léxico definido en un exterior llamado subrutina.

Cuando la subrutina interior se llama, será ver el valor de la variable el exterior de subrutina como lo era antes y durante el primera llamada a la subrutina exterior; en este caso, después de se completa la primera llamada a la subrutina externa , las subrutinas interior y exterior ya no compartirán un valor común para la variable. En es decir, la variable ya no se compartirá .

Este problema generalmente se puede resolver por haciendo que la subrutina interna sea anónima, utilizando la sintaxis sub {}. Cuando los internos subs anónimos que hacen referencia a variables en subrutinas externas son creados, son automáticamente rebote a los valores actuales de dichas variables .

Código fijo utilizando sub anónima:

# .... 
my $connected_sub; 
$connected_sub = sub { 
    no warnings 'recursion'; 
    my $node = shift; 
    return if exists $marked{$node}; # Line 280 
    $marked{$node} = 1; 
    push @stack, $node; # Line 282 
    my $children = $links{$node}; # Line 283 
    &$connected_sub($_) for keys %$children; 
}; 

for my $node (sort keys %links) { 
    next if exists $marked{$node}; 
    @stack =(); 
    &$connected_sub($node); 
    #print "@stack\n"; 
    push @all_ccomp, [@stack]; 
} 
# .... 
+0

Gracias. Traté de arreglarlo con sub. Pero tengo un error. Por favor mira mi actualización – neversaint

+0

Lo siento. Fijo. Recibí mi estúpido error. – neversaint

+0

Conocía esta respuesta, y siempre he resuelto el problema de una de las maneras estándar, ya sea por subs anónimos o por pasar argumentos. // Pero ambos son un poco feos. // En este momento, estoy mirando una situación donde 'el valor de la variable externa tal como era durante la primera llamada' es exactamente lo que quiero. En este caso, porque no se supone que la variable cambie durante la vida de la función interna. // Entonces me pregunto ... ¿debería? ... –

6

Al conseguir un mensaje de diagnóstico de Perl, por lo general es una buena idea para retirar perldiag para averiguar lo que significa. Esa página de manual también cubre la advertencia que está recibiendo.

Básicamente, las subrutinas nombradas no anidan en la forma en que usted las esperaba. Las soluciones incluyen el uso de subrutinas internas anónimas, no anidando subrutinas con nombre y simplemente pasando estado entre ellas explícitamente, o usando algo como mysubs de CPAN.

0

Este error también puede ocurrir si usted ha declarado querer volver a variables compartidas en el hilo conductor de una secuencia de comandos,

`

use vars qw(%types %colors); 

my %types = (...); # bad 
%colors = (...); # good 

`

5

Otra forma (quizá más simple) out es declarar variables como "nuestro" en lugar de "mi"

Entonces,

our %marked; 

en lugar de

my %marked; 

etc.

+1

ver http://stackoverflow.com/questions/845060/what-is-the-difference-between-my-and-our-in-perl para más información sobre 'our' – chicks

Cuestiones relacionadas