In che modo $_ è diverso dall'input denominato o dagli argomenti del ciclo?

StackOverflow https://stackoverflow.com/questions/5405423

  •  29-10-2019
  •  | 
  •  

Domanda

Dato che uso molto $_, voglio capirne meglio l'utilizzo.$_ è una variabile globale per valori impliciti per quanto l'ho capita e usata.

Dato che $_ sembra essere impostato comunque, ci sono motivi per utilizzare variabili di ciclo con nome su $_ Oltretutto leggibilità?

In quali casi è importante che $_ sia una variabile globale?

Quindi se uso

for (@array){
    print $_;
}

o anche

print $_ for @array;

ha lo stesso effetto di

for my $var (@array){
    print $var;
}

Ma funziona lo stesso?Immagino che non sia esattamente così, ma quali sono le differenze effettive?

Aggiornamento:

Sembra che $_ abbia anche l'ambito corretto in questo esempio.Non è più globale?Sto usando 5.12.3.

#!/usr/bin/perl
use strict;
use warnings;

my @array = qw/one two three four/;
my @other_array = qw/1 2 3 4/;

for (@array){
    for (@other_array){
        print $_;
    }
    print $_;
}

che stampa correttamente 1234uno1234due1234tre1234quattro.

Per $_ globale mi sarei aspettato 1234 4 1234 4 1234 4 1234 4 ..o mi sto perdendo qualcosa di ovvio?

Quando $_ sarà globale allora?

Aggiornamento:

Ok, dopo aver letto più attentamente le varie risposte e perlsyn sono arrivato ad una conclusione:

Oltre alla leggibilità è meglio evitare di usare $_ perché la localizzazione implicita di $_ deve essere conosciuta e tenuta in considerazione altrimenti si potrebbero riscontrare comportamenti inattesi.

Grazie per il chiarimento in merito.

È stato utile?

Soluzione

are there reasons to use named loop variables over $_ besides readability?

Il problema non è se vengono nominati o meno.Il problema è se si tratta di "variabili di pacchetto" o "variabili lessicali".

Vedi l'ottima descrizione dei 2 sistemi di variabili usati in Perl "Coping with Scoping":

http://perl.plover.com/FAQs/Namespaces.html

le variabili del pacchetto sono variabili globali e dovrebbero quindi essere evitate per tutti i soliti motivi (ad es. azioni a distanza).

Evitare le variabili del pacchetto è una questione di "funzionamento corretto" o "più difficile iniettare bug" piuttosto che una questione di "leggibilità".

In what cases does it matter $_ is a global variable?

Ovunque.

La domanda migliore è:

In what cases is $_ local()ized for me?

Ci sono alcuni posti in cui Perl local () ize $ _ per te, principalmente foreach, grep e map.Tutti gli altri luoghi richiedono che tu local () ize tu stesso, quindi inietterai un potenziale bug quando inevitabilmente dimenticherai di farlo.:-)

Altri suggerimenti

La classica modalità di errore di utilizzare $_ (implicitamente o esplicitamente) come variabile di ciclo è

for $_ (@myarray) {
  /(\d+)/ or die;
  foo($1);
}

sub foo {
  open(F, "foo_$_[0]") or die;
  while (<F>) {
    ...
  }
}

dove, poiché la variabile loop in for / foreach è associata alla voce di elenco effettiva, significa che while (<F>) sovrascrive @myarray con le righe lette dai file.

$ _ equivale a denominare la variabile come nel secondo esempio con il modo in cui viene solitamente utilizzata.$ _ è solo un nome della variabile di default di una scorciatoia per l'elemento corrente nel ciclo corrente da salvare sulla digitazione quando si esegue un ciclo semplice e veloce.Tendo a usare variabili denominate piuttosto che quelle predefinite.Rende più chiaro di cosa si tratta e se mi capita di dover fare un ciclo annidato non ci sono conflitti.

Poiché $ _ è una variabile globale, potresti ottenere valori imprevisti se provi a utilizzare il suo valore che aveva da un blocco di codice precedente.Il nuovo blocco di codice può far parte di un ciclo o di un'altra operazione che inserisce i propri valori in $ _, sovrascrivendo ciò che ci si aspettava che fosse lì.

Il rischio nell'uso di $ _ è che è globale (a meno che tu non lo localizzi con local $_), e quindi se alcune funzioni che chiami nel loop utilizzano anche $ _, i due usi possono interferire.

Per motivi che non mi sono chiari, questo mi ha solo morso di tanto in tanto, ma di solito localizzo $ _ se lo uso all'interno dei pacchetti.

Non c'è niente di speciale $_ a parte questo è il parametro predefinito per molte funzioni.Se espliciti l'ambito lessicale del tuo file $_ con my, perl utilizzerà la versione locale di $_ piuttosto che quello globale.Non c'è niente di strano in questo, è proprio come qualsiasi altra variabile con nome.

sub p { print "[$_]"; } # Prints the global $_
# Compare and contrast
for my $_ (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex1
for my $_ (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex2
for       (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex3
for       (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex4

Dovresti rimanere un po' disorientato dall'output finché non scopri che perl conserverà il valore originale della variabile del ciclo all'uscita dal ciclo (vedi perlsyn).

Nota es2 Sopra.Qui il secondo ciclo utilizza l'ambito lessicale $_ dichiarato nel primo ciclo.Sottile, ma previsto.Ancora una volta, questo valore viene preservato all'uscita, quindi i due cicli non interferire.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top