2010-10-21 6 views
10

¿Cómo puedo pasar dos matrices y una cadena a un submarino?¿Cómo puedo pasar dos matrices y una cadena a una subrutina Perl?

Aquí es lo que estoy tratando de hacer:

use strict; 
use warnings; 

my @x = qw(AAAA BBBB CCCC DDDD EEEE); 
my @y = qw(1111 2222 3333 4444 5555); 

my $z = "hello"; 

Hello(@x,@y,$z); 

exit(0); 

sub Hello { 

    my (@x,@y,$z) = @_; 

    print "$_\n" for @x; 
    print "$_\n"; 
    print "$_\n" for @y; 
    print "$_\n"; 
    print "$z\n"; 
} 

Salida:

AAA 
BBBB 
CCCC 
DDDD 
EEEE 
1111 
2222 
3333 
4444 
5555 
hello 
Use of uninitialized value $_ in concatenation (.) or string at test.pl line 19. 

Use of uninitialized value $_ in concatenation (.) or string at test.pl line 21. 

Use of uninitialized value $z in concatenation (.) or string at test.pl line 22. 

Respuesta

15

Tiene que pasar cada una de las matrices como una referencia, de lo contrario su @x en el sub engullirá toda la matriz de argumentos, dejando @y un arraay vacío y $z un valor undef.

Esto sucede porque the comma operator - en un contexto lista - a su vez, un @x, @y, $z en una sola matriz que consiste de todos los elementos de @x seguidas por todos los elementos de @y y luego un valor de $z; su @x en el sub engullirá toda la matriz de argumentos combinada, dejando @y como una matriz vacía y $z como valor undef.

Otra posible fuente de confusión es el hecho de que nombró las dos variables @x, a pesar de que son completamente independientes entre sí debido a las reglas de alcance. Una buena práctica sería nombrarles algo distinto para evitar tener que adivinar cuál pretendía usar, p. Ej. llame al primer arreglo de la subrutina @x2.

Tenga en cuenta que puede pasar la matriz como referencia de una de dos maneras: la referencia a la matriz original (aproximación real de paso por referencia) y la referencia a una COPIA de la matriz, que se comportará como si quisieras que tu código origainal se comporte y pase de valor.

use strict; use warnings; 

my @x = qw(AAAA BBBB CCCC DDDD EEEE); 
my @y = qw(1111 2222 3333 4444 5555); 
my $z = "hello"; 

Hello(\@x,\@y,$z); 

# If you wish to pass a reference of a COPY of the array, 
# so that you can modify it inside the subroutine without modifying the original, 
# instead call Hello([@x], [@y], $z); 

exit(0); 

sub Hello { 

    my ($x2,$y2,$z2) = @_; 
    # Now, you de-reference array reference $x2 via @$x2 or $x2->[$i] 
    # where previously you used @x2 or $x2[$i] 
    print "$_\n" for @$x2; 
    print "$_\n"; 
    print "$_\n" for @$y2; 
    print "$_\n"; 
    print "$z2\n"; 

} 
3

Tiene que pasar en las referencias de la matriz:

sub Hello { 
    my ($x_ref, $y_ref, $z) = @_; 
    my @x = @$x_ref; 
    my @y = @$y_ref; 
    ... 
} 

Hello(\@x, \@y, $z); 
8

es necesario utilizar referencias:

sub Hello { 
    my ($x, $y, $z) = @_; 
    print "$_\n" for @$x; 
    ... 
} 

Hello(\@x, \@y, $z); 

también se puede utilizar prototipos de subrutinas de Perl para eliminar la \ en el sitio de llamada :

sub Hello (\@\@$) {...} 

Hello(@x, @y, $z); 

El prototipo (\@\@$) le dice al compilador que los argumentos a Hello tendrán contexto de referencia de matriz en los primeros dos args y contexto escalar en el tercer arg. Los prototipos no son para la validación de argumentos, sino que le permiten escribir subrutinas que funcionan como las construcciones internas. En este caso, como push.

Como DVK menciona en un comentario a continuación, PBP recomienda no utilizar prototipos como regla general, ya que tienden a ser utilizados de forma inadecuada para la validación de argumentos. Considero que usar ciertas características de prototipos (\% o \@ para imponer contexto de referencia para varios tipos, o & como primer arg para permitir map como sintaxis de bloque) justifica la ruptura con PBP. Particularmente cierto es si el sub se está utilizando para extender la sintaxis de Perl (funciones auxiliares, funciones que son solo azúcar sintáctico ...)

+0

en el interés de la divulgación completa, libro de Perl Best Practices desalienta el uso de prototipos sub (Me arriba-Vote su respuesta si se aclaró thusly) - http://stackoverflow.com/questions/3991474/ is-using-prototypes-to-declare-array-reference-context-on-subroutine-args-a-good/3991558 # 3991558 – DVK

1
use strict; use warnings; 

my @x = qw(AAAA BBBB CCCC DDDD EEEE); my @y = qw(1111 2222 3333 4444 5555); 

my $z = "hello"; 

Hello(\@x,\@y,$z); 

exit(0); 

sub Hello { 
    my ($x,$y,$z) = @_; 

    print "$_\n" for @$x; 
    print "$_\n" for @$y; 
    print "$z\n"; 

} 
Cuestiones relacionadas