2012-04-03 18 views
11

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

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"; 
} 

Esta impresora:

 
AFTER SHIFT IN SUB: one 
POST SUBROUTINE: zero 

esperaba que imprime one en ambas ocasiones.

Así que mi pregunta es doble:

1) ¿Por qué no se comporta de la manera que cree 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.

Respuesta

9

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 dicho eliminación de referencias que crea el problema, pero utilizando @$array todavía se derreferenciándolo. Como señaló @mob, la asignación de la variable es lo que crea la nueva matriz en lugar de actualizar la referencia existente.

+0

Wow. Ese es un matiz que no entendí. ¡Gracias! – BlairHippo

+1

@mob estás en lo correcto. Al editar mi respuesta para aclarar – Cfreak

+2

, tenga en cuenta que con Perl 5.14+ puede escribir 'shift $ array' en el sub y que la eliminación de referencias ocurre automágicamente. – mirod

0

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

prefiero ser más consistente en el uso de las referencias de matriz para reducir al mínimo 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"; 
} 
Cuestiones relacionadas