Pregunta

Sé que pasar un escalar a un submarino está pasando la referencia, pero como soy nuevo en Perl, todavía hice la siguiente prueba:

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

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

¿Fue útil?

Solución

Es porque su segunda declaración de impresión es equivalente a hacer esto ...

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

Cuando lo que quieres es

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

En otras palabras, la eliminación de referencias ocurre antes de evaluar el subíndice de matriz.

Cuando agrega esas casas curlas, le dice a Perl cómo interpretar la expresión como lo desea; evaluará $_[0] Primero, y luego desreferencia para obtener el valor.

Otros consejos

Es una cosa de orden de evaluación.

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

Este es el elemento 0 de la referencia de la variable escalar $ _. Primero toma la referencia y luego está tratando de encontrar el elemento 0.

  ${$_[0]}

Esta es una referencia al elemento 0 de la matriz @_. Primero encontrará el elemento 0 y luego tomando una referencia de eso.

Si te configuras use strict y use warnings En la parte superior de su código, verá muchas advertencias sobre valores indefinidos de su primer intento.

$$_[0] es como $foo[0], solo 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, utilizando la alternativa -> sintaxis. La sintaxis para la deserencia puede parecer arbitraria y difícil de recordar, pero hay sentido y orden subyacente; Una muy buena presentación es en http://perlmonks.org/?node=references+quick+Reference.

No tienes que pasar una referencia a $i. La notación $_[0] es un alias por $i Cuando lo invocas 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 este:

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';

Producción:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top