Pregunta Modificar matriz en subrutina


Tengo un código que no funciona de la manera que esperaba, y agradecería algo de ayuda para descubrir cómo hacerlo funcionar de la manera que YO ESPERO.

Me gustaría usar una subrutina para modificar una matriz de entrada. Pensé que si pasaba una referencia a la matriz, cualquier cambio que realizara se reflejaría también en la versión de la persona que llama. Pero aparentemente no funciona de esa manera.


my @test_array = qw (zero one two three);

shift_array(\@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

sub shift_array {
    my @array = @{(shift)};
    shift @array;
    print "AFTER SHIFT IN SUB: $array[0]\n";
}

Esto imprime:

DESPUÉS DE CAMBIO EN SUB: uno
POST SUBROUTINO: cero

Esperaba que se imprimiera one ambas veces.

Entonces mi pregunta es doble:

1) ¿Por qué no se está comportando como creo que debería? ¿Pasar una referencia a una matriz crea una copia de la matriz?

2) ¿Cómo obtengo el comportamiento que estaba esperando? ¿Cómo obtengo una subrutina para deslizar uno o más elementos fuera de la parte frontal de la copia de una matriz de entrada?

Gracias de antemano por cualquier información que pueda ofrecer.


12
2018-04-03 14:53


origen


Respuestas:


Porque my @array es una nueva matriz a la que asignó la matriz original desreferenciada. Es una copia.

En lugar de hacer esto:

sub shift_array {
    my $array = shift;
    shift( @$array );
}

Editar: Originalmente dije que desreferenciar crea el problema pero usando @$array todavía está desreferencing. Como señaló @mob, la asignación de la variable es lo que crea la nueva matriz en lugar de actualizar la referencia existente.


9
2018-04-03 14:56



Este es uno de los (muy pocos) casos en que los prototipos de Perl son útiles.

#!/usr/bin/perl

use strict;
use warnings;

# Prototype forces the first argument to be a reference to an array    
sub shift_array (\@) {
  my $array = shift;
  shift(@$array);
  print "AFTER SHIFT IN SUB: @$array[0]\n";
}

my @test_array = qw (zero one two three);

shift_array(@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

0
2018-04-04 08:58



Prefiero ser más consistente en el uso de referencias de matriz para minimizar la ambigüedad:

#!/usr/bin/perl
use strict;
use warnings;

my @test_array = qw (zero one two three);

shift_array(\@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

sub shift_array {
    my $ref = shift;
    shift @$ref;
    print "AFTER SHIFT IN SUB: ${$ref}[0]\n";
}

0
2018-01-21 06:32