¿Cómo puedo pasar una matriz a una función en Perl?
Frecuentes
Visto 3,497 veces
6
Pregunta 1:
Quiero pasar una matriz a una función. Pero el argumento pasado se cambia en la función. ¿Se llama por valor?
Pregunta 2:
#my ($name, $num, @array)= @_; <=1 )
my $name = shift; <=2 )
my $num = shift;
my @array = shift;
Los casos 1 y 2 tienen una salida diferente. ¿Por qué ocurrió?
#!/usr/bin/perl
use strict;
my @test1;
push @test1, ['a', 1];
push @test1, ['b', 1];
push @test1, ['c', 1];
push @test1, ['d', 1];
push @test1, ['e', 1];
for (my $i=0; $i< scalar(@test1); $i++) {
print "out1: $test1[$i][0] $test1[$i][1]\n";
}
test_func("test_func", 10, @test1);
sub test_func {
#my ($name, $num, @array)= @_; <=1)
my $name = shift; <=2)
my $num = shift;
my @array = shift;
print "$name\n";
print "$num\n";
for (my $i=0; $i< scalar(@test1); $i++) {
print "$array[$i][0] $array[$i][1]\n";
}
for (my $i=0; $i< scalar(@test1); $i++) {
if ($array[$i][0] eq 'a') {
$array[$i][0] = 'z';
}
}
for (my $i=0; $i< scalar(@test1); $i++) {
print "change: $array[$i][0] $array[$i][1]\n";
}
}
for (my $i=0; $i< scalar(@test1); $i++) {
print "out2: $test1[$i][0] $test1[$i][1]\n";
}
#
A continuación se muestra la salida de prueba.
out1: a 1
out1: b 1
out1: c 1
out1: d 1
out1: e 1
test_func
10
a 1
b 1
c 1
d 1
e 1
change: z 1
change: b 1
change: c 1
change: d 1
change: e 1
out2: z 1 <= Why did it change?
out2: b 1
out2: c 1
out2: d 1
out2: e 1
1 Respuestas
11
Quiero pasar una matriz a una función [...] tiene una salida diferente. ¿Por qué ocurrió?
No puede pasar una matriz a un función sub. Los subs solo pueden tomar una lista de escalares como argumentos.
test_func("test_func", 10, @test1);
es el mismo que
test_func("test_func", 10, $test1[0], $test1[1], $test1[2], $test1[3], $test1[4]);
Estás creando una nueva matriz en test_func
Cuando tu lo hagas
my ($name, $num, @array) = @_;
shift
devuelve el primer elemento de @_
, que es necesariamente un escalar. @_
es un arreglo, y los elementos de los arreglos son escalares. el equivalente seria
my $name = shift(@_);
my $num = shift(@_);
my @array = splice(@_);
Para pasar una matriz a un sub, normalmente se le pasaría una referencia.
test_func("test_func", 10, \@test1);
my ($name, $num, $array) = @_;
my $name = shift;
my $num = shift;
my $array = shift;
say "@$array";
Pero el argumento pasado se cambia en la función. ¿Se llama por valor?
Perl nunca pasa por valor. Siempre pasa por referencia. Si cambia algún elemento de @_
, cambiará el argumento correspondiente en la persona que llama.
$ perl -E'sub f { $_[0] = "def"; } my $x = "abc"; f($x); say $x;'
def
Pero ese no es el problema. No cambias ningún elemento de @_
. Lo que está haciendo es cambiar la matriz única a la que hacen referencia ambos $test[0]
y $array[0]
.
Esto es lo que estas haciendo:
my $ref1 = [ 'a', 1 ]; # aka $test1[0]
my $ref2 = $ref1; # aka $array[0]
$ref2->[0] = 'z'; # Changes the single array (not $ref1 or $ref2).
Es corto para
my @anon = ( 'a', 1 );
my $ref1 = \@anon; # aka $test1[0]
my $ref2 = $ref1; # aka $array[0]
$ref2->[0] = 'z'; # Changes @anon (not $ref1 or $ref2).
Almacenable's dclone
se puede usar para hacer una "copia profunda" de una matriz.
my $ref1 = [ 'a', 1 ];
my $ref2 = dclone($ref1); # clones the reference, the array, 'a' and 1.
$ref1->[0] = 'y'; # Changes the original array
$ref2->[0] = 'z'; # Changes the new array
respondido 15 nov., 15:21
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas arrays perl function or haz tu propia pregunta.
gracias por tu amable explicación. resuelvo mi problema difícil ^^ - user1395438
si esta solución ha ayudado, marque la marca de verificación junto a ella - Joel Berger
...y si no, cuéntanos qué falta. - Ikegami