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.