2011-05-14 17 views

Respuesta

7

La matriz de argumento @_ no se comporta de la manera en que cree que lo hace. Los valores en @_ en una subrutina son en realidad aliases for the real arguments:

El array @_ es una matriz local, pero sus elementos son alias para los parámetros escalares reales.

Cuando se dice esto:

sub s { 
    "huh?" =~ /(.*)/; 
    print for @_; 
} 

"ok" =~ /(.*)/; 
s("$1", $1); 

El $1 en el primer argumento a s se evalúa inmediatamente por la interpolación de cadenas pero el segundo argumento no se evalúa, es justo señalar que el segundo valor la versión del submarino de @_ es $1 (la variable real $1, no su valor). Luego, dentro de s, el valor de $1 se cambia por su expresión regular. Y ahora, su @_ tiene un alias para la cadena "ok" seguido de un alias para $1, estos alias se resuelven con el print en su ciclo.

Si cambia la función a esto:

sub s { 
    my @a = @_; 
    "huh?" =~ /(.*)/; 
    print for @a; 
} 

o incluso esto:

sub s { 
    local $1; 
    "huh?" =~ /(.*)/; 
    print for @_; 
} 

Luego le ponen las dos líneas de "ok" que se está esperando. Lo gracioso (curioso, no gracioso, ja, ja) es que esas dos versiones de s producen el resultado esperado por diferentes razones.La versión my @a = @_; extrae los valores actuales de los alias en @_ antes de que la expresión regular tenga sus manos en $1; la local $1; version localiza la variable $1 a la sub dejando el alias en @_ referencia a la versión de $1 desde fuera del sub:

Un modifica local de las variables que se enumeran a ser local en el bloque que lo contiene, un archivo o eval.

las singularidades de este tipo son eso que siempre debe copiar los valores de las variables de captura de expresiones regulares numeradas a las variables de su tan pronto como sea posible y por qué se desea expandir @_ justo al inicio de sus funciones (a menos que sepa por qué no quieres hacer eso).

Afortunadamente no he abusado demasiado de la terminología, este es uno de esos rincones extraños de Perl del que siempre me he mantenido alejado porque no me gusta hacer malabares con hojas de afeitar.

2

El código de ejemplo hace uso de dos hechos:

  • Los elementos de la matriz @_ son alias para los parámetros escalares reales. En particular, si se actualiza un elemento $_[0], se actualiza el argumento correspondiente (y viceversa).
  • $1 es una variable global (aunque tiene un alcance dinámico para el BLOQUE actual), que contiene automáticamente el subpatrón de () desde la última coincidencia de patrón exitosa.

El primer argumento de la subrutina es una cadena ordinaria ("ok"). El segundo argumento es la variable global $1. Pero se cambia por la coincidencia de patrón exitosa dentro de la subrutina, antes de que se impriman los argumentos.

1

Eso sucede porque perl pasa los parámetros por referencia.

Lo que está haciendo es similar a:

my $a = 'ok'; 

sub foo { 
    $a = 'huh?'; 
    print for @_; 
} 

my $b = $a; 
foo($b, $a) 

Cuando el foo sub se llama, $ _ [1] es en realidad un alias de $ ay por lo que su valor es modificado cuando se modifica $ a.