Domanda

Ecco un semplice Perl per contare il numero di volte in cui si verifica un valore in un array. Questo funziona senza alcun avviso.

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{

Ecco un semplice Perl per contare il numero di volte in cui si verifica un valore in un array. Questo funziona senza alcun avviso.

$histogram{

Ecco un semplice Perl per contare il numero di volte in cui si verifica un valore in un array. Questo funziona senza alcun avviso.

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{

Ecco un semplice Perl per contare il numero di volte in cui si verifica un valore in un array. Questo funziona senza alcun avviso.

<*>

Quando il corpo del loop viene modificato in

<*>

Perl avverte " Uso di valore non inizializzato in aggiunta " ;.

Cosa sta succedendo sotto il cofano? Perché il valore viene inizializzato quando fornito come operando all'operatore ++ e non inizializzato con l'operatore +?

}++; }

Quando il corpo del loop viene modificato in

<*>

Perl avverte " Uso di valore non inizializzato in aggiunta " ;.

Cosa sta succedendo sotto il cofano? Perché il valore viene inizializzato quando fornito come operando all'operatore ++ e non inizializzato con l'operatore +?

} = $histogram{

Ecco un semplice Perl per contare il numero di volte in cui si verifica un valore in un array. Questo funziona senza alcun avviso.

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{

Ecco un semplice Perl per contare il numero di volte in cui si verifica un valore in un array. Questo funziona senza alcun avviso.

<*>

Quando il corpo del loop viene modificato in

<*>

Perl avverte " Uso di valore non inizializzato in aggiunta " ;.

Cosa sta succedendo sotto il cofano? Perché il valore viene inizializzato quando fornito come operando all'operatore ++ e non inizializzato con l'operatore +?

}++; }

Quando il corpo del loop viene modificato in

<*>

Perl avverte " Uso di valore non inizializzato in aggiunta " ;.

Cosa sta succedendo sotto il cofano? Perché il valore viene inizializzato quando fornito come operando all'operatore ++ e non inizializzato con l'operatore +?

} + 1;

Quando il corpo del loop viene modificato in

<*>

Perl avverte " Uso di valore non inizializzato in aggiunta " ;.

Cosa sta succedendo sotto il cofano? Perché il valore viene inizializzato quando fornito come operando all'operatore ++ e non inizializzato con l'operatore +?

}++; }

Quando il corpo del loop viene modificato in

<*>

Perl avverte " Uso di valore non inizializzato in aggiunta " ;.

Cosa sta succedendo sotto il cofano? Perché il valore viene inizializzato quando fornito come operando all'operatore ++ e non inizializzato con l'operatore +?

È stato utile?

Soluzione

L'operatore + valuta sia il modulo a sinistra che il modulo a destra, quindi restituisce la somma di entrambi. La valutazione della chiamata hash non vede alcun contesto speciale.

L'operatore ++ ha qualche magia speciale integrata. Citando dalla manpage di perlop, riguardo all'operatore ++:

  

" undef " viene sempre trattato come un valore numerico e in particolare viene modificato su 0 prima dell'incremento (in modo che un post-incremento di un valore indefinito restituisca 0 anziché "undef").

modifica : per approfondire la differenza, ++ modifica il valore in atto, mentre + prende semplicemente i suoi argomenti come input. Quando + vede un valore indefinito, in genere qualcosa è andato storto, ma per ++, il tuo esempio di manipolazione dell'hash è molto tipico: l'utente vuole considerare undef come 0, invece di dover controllare e inizializzare ogni volta. Quindi sembra logico trattare questi operatori in questo modo.

Altri suggerimenti

Non è che Perl inizializzi necessariamente i valori, ma che non li avverte sempre. Non cercare di pensare a una regola per questo perché troverai sempre delle eccezioni e proprio quando pensi di averlo capito, la prossima versione di Perl cambierà gli avvisi su di te.

In questo caso, come ha affermato Harleqin, gli operatori di auto-incremento hanno un caso speciale.

Alcuni operatori omettono deliberatamente il "non inizializzato" avvertimento per la vostra convenienza perché sono comunemente usati in situazioni in cui 0 o "quot" " il valore predefinito per l'operando di sinistra o unico ha senso.

Questi sono: ++ e - (pre o post), + =, - =,. =, | =, ^ =, & amp; & amp; =, || =.

Nota che alcuni di questi danno erroneamente l'avvertimento quando usato su una variabile legata: vedi i test contrassegnati TODO in http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.t .

Come ha detto Brian: lo fa ancora, ti avverte. Gli avvertimenti ti informano su alcune manipolazioni con effetti che potresti non aver inteso.

Stai specificatamente chiedendo il valore di $ histogram {$ _} , aggiungendo 1 ad esso e quindi assegnandolo allo stesso slot. È lo stesso modo in cui non mi aspetto che l'autovivificazione funzioni qui:

my $hash_ref = $hash_for{$key_level_1};
$hash_ref->{$key_level_2} = $value;

come fa qui:

$hash_for{$key_level_1}{$key_level_2} = $value;

La magia probabilmente non funziona come l'ottimizzazione. E l'ottimizzazione del compilatore noterebbe che a = a + 1 è la stessa cosa di a ++ , quindi se ci fosse un operatore di incremento nel linguaggio assembly, potrebbe invece usare quell'istruzione ottimizzata di fingere che fosse necessario per preservare il primo valore e quindi di sovrascriverlo perché non era effettivamente necessario.

L'ottimizzazione richiede ulteriore controllo e spese generali una volta per migliorare le prestazioni ad ogni corsa. Ma in un linguaggio dinamico non vi è alcuna garanzia che non si aggiunga un overhead alla stessa velocità che altrimenti si tenterebbe di ridurlo.

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