2011-05-03 15 views
5

Sé que pasar un escalar a un sub está realmente pasando la referencia, pero como yo soy nuevo en perl Todavía hice la siguiente prueba:pasando una referencia escalar en Perl

#!/usr/bin/perl 
$i = 2; 
subr(\$i); 
sub subr{ 
    print $_[0]."\n"; 
    print $$_[0]."\n"; 
} 

pensé la primera línea va a imprimir una dirección y la segunda línea va a devolver el número, pero la segunda es una línea en blanco. Fui señalado por alguien más para hacer esto: ${$_[0]} e imprime el número. Pero no sabía la razón por la que sin {} no funciona y por qué funciona con {}. Entonces, ¿qué ha sucedido?

Respuesta

13

Es debido a su estado de segunda impresión es equivalente a hacer esto ...

my $x = $$_; print $x[0]; 

Cuando lo que desea es

my $x = $_[0]; print $$x; 

En otras palabras, la desindexación se produce antes de que el subíndice de matriz es evaluado

Cuando agrega esas curl-wurlies, le dice a perl cómo interpretar la expresión como la quiere; primero evaluará $_[0] y luego lo desvinculará para obtener el valor.

+0

Esto es genial, gracias – user685275

7

Es una cuestión de orden de evaluación.

$$_[0] is evaluated as {$$_}[0] 

Este es el 0 ° elemento de la referencia de la variable escalar $ _. Toma la referencia primero y luego trata de encontrar el 0 ° elemento.

${$_[0]} 

Esta es una referencia al 0 ° elemento de la matriz @_. Es encontrar el 0 ° elemento primero y luego tomar una referencia de eso.

Si configura use strict y use warnings en la parte superior de su código, verá un montón de advertencias sobre los valores indefinidos de su primer intento.

+0

Esto es genial, gracias – user685275

1

No es necesario que pase una referencia al $i. La notación $_[0] es un alias para $i cuando lo invoca como subr($i).

use strict; 
use warnings; 
use Test::More tests => 2; 

sub subr{ $_[0]++ } # messing with exactly what was passed first 
my $i=2; 
is($i, 2, q[$i == 2]); 
subr($i); 
is($i, 3, q[$i == 3]); 

Otro ejemplo es la siguiente:

use strict; 
use warnings; 
use Test::More tests => 6; 
use Test::Exception; 

sub subr{ $_[0]++ } 
my $i=2; 
is($i, 2, q[$i == 2]); 
subr($i); 
is($i, 3, q[$i == 3]); 

sub subr2 { $_[0] .= 'x'; } 
dies_ok { subr2('lit'); } 'subr2 *dies* trying to modify a literal'; 
lives_ok { 
    my $s = 'lit'; 
    subr2($s); 
    is($s, 'litx', q[$s eq 'litx']); 
    subr2((my $s2 = 'lit')); 
    is($s2, 'litx', q[$s2 eq 'litx']); 
} 'subr2 lives with heap variables'; 

Salida:

ok 1 - $i == 2 
ok 2 - $i == 3 
ok 3 - subr2 *dies* trying to modify a literal 
ok 4 - $s eq 'litx' 
ok 5 - $s2 eq 'litx' 
ok 6 - subr2 lives with heap variables 
1..6 
3

$$_[0] es como $foo[0], sólo que con $ _ en lugar del nombre de la matriz. Esto significa que $ _ se trata como una referencia de matriz, y la expresión no implica la referencia escalar $_[0] en absoluto. $_->[0] es equivalente, usando la sintaxis -> alternativa. La sintaxis para la desreferenciación puede parecer arbitraria y difícil de recordar, pero existe un sentido y orden subyacentes; una muy buena presentación de la misma está en http://perlmonks.org/?node=References+quick+reference.

Cuestiones relacionadas