2011-05-14 12 views

risposta

7

L'array di argomenti @_ non si comporta come si pensa. I valori in @_ in una subroutine sono effettivamente aliases for the real arguments:

L'array @_ è una matrice locale, ma i suoi elementi sono alias per i parametri effettivi scalari.

Quando si dice questo:

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

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

Il $1 nel primo argomento a s è immediatamente valutate dalla interpolazione stringa, ma il secondo argomento non viene valutata, è solo osservato che il secondo valore in la versione sub di @_ è $1 (la variabile attuale $1, non il suo valore). Quindi, all'interno di s, il valore di $1 viene modificato dall'espressione regolare. E ora, il tuo @_ ha un alias per la stringa "ok" seguito da un alias per $1, questi alias vengono risolti dallo print nel tuo ciclo.

Se si modifica la funzione a questo:

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

o anche questo:

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

allora avrai le due linee di "ok" che vi aspettate. Il divertente (strano strano, non divertente ha-ha) è che quelle due versioni di s producono il risultato atteso per diversi motivi.La versione my @a = @_; estrae i valori correnti degli alias in @_ prima che l'espressione regolare ottenga le proprie mani su $1; la local $1; version localizza la variabile $1 al sub lasciando l'alias in @_ riferimento alla versione di $1 dall'esterno sub:

Una modifica locale le variabili elencate sia locale al blocco, file, o eval.

Stravaganti come questo sono il motivo per cui si dovrebbe sempre copiare i valori delle variabili di cattura regex numerati alle variabili del vostro al più presto possibile e perché si desidera decomprimere @_ proprio all'inizio delle vostre funzioni (se non si sa perché tu non vuoi farlo).

Speriamo di non aver macellato troppo la terminologia, questo è uno di quegli strani angoli di Perl a cui sono sempre stato lontano perché non mi piacciono le lame da rasoio da giocoliere.

2

Il codice di esempio fa uso di due fatti:

  • Gli elementi dell'array @_ sono alias per i parametri effettivi scalari. In particolare, se un elemento $_[0] viene aggiornato, l'argomento corrispondente viene aggiornato (e viceversa).
  • $1 è una variabile globale (anche se dinamicamente confinata al BLOCCO corrente), che contiene automaticamente il subpattern da () dall'ultima corrispondenza di modello riuscita.

Il primo argomento della subroutine è una stringa ordinaria ("ok"). Il secondo argomento è la variabile globale $1. Ma viene modificato dalla corrispondenza del pattern riuscita all'interno della subroutine, prima che gli argomenti vengano stampati.

1

Ciò accade perché perl passa i parametri per riferimento.

Quello che state facendo è simile a:

my $a = 'ok'; 

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

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

Quando il sub foo è chiamata, $ _ [1] è in realtà un alias per $ a e quindi il suo valore viene modificato quando $ A viene modificato.