2009-03-02 12 views
5

Mi sono imbattuto nella seguente riga di codice. Ha problemi:

  • è destinato a fare la stessa spinta
  • avrebbe dovuto utilizzare spinta
  • è difficile da leggere, capire
  • Da allora ho cambiato da usare spinta
  • lo fa qualcosa che ho pensato è stata illegale, ma chiaramente non è

qui è:

$array [++$#array] = 'data'; 

La mia domanda è: cosa significa pre-incrementare $ # array? Ho sempre considerato $ # array come un attributo di un array e non scrivibile.

+0

Grazie per la modifica - che è il titolo avrei dovuto scrivere. –

risposta

14

perldata dice:

"La lunghezza di un array è un valore scalare È possibile trovare la lunghezza del @giorni valutando $ # giorni, come in csh Tuttavia, questo non è la lunghezza del.. la matrice, è il pedice dell'ultimo elemento, che è un valore diverso poiché di solito c'è un elemento 0. Assegnare a $ # giorni cambia effettivamente la lunghezza dell'array. Accorciare un array in questo modo distrugge i valori intermedi. precedentemente abbreviato non recupera i valori che erano in quegli elementi. "

La modifica di $ # array è utile in alcuni casi, ma in questo caso, è meglio spingere chiaramente.

+0

Uno dei casi in cui sarebbe meglio è quando sai in anticipo quanto grande sarà il tuo array alla fine. Con enormi matrici questo ti darà un grande incremento di prestazioni. – innaM

+0

In caso di allungamento di Perls precedente utilizzando l'array $ #, si otterrebbero i valori precedenti. –

+0

Questo era perl4, credo. – ysth

4

L'assegnazione di un valore superiore alla lunghezza dell'array corrente a $#array estende la matrice.

+0

Credo che il collegamento sia a una copia non autorizzata di un libro. Ti suggerirei di rimuoverlo. – mirod

+0

In realtà, il collegamento è già morto, ma sono d'accordo sul fatto che sia una cattiva idea collegarsi a libri piratati. – Telemachus

+0

Non è morto quando ho controllato, e c'erano anche un sacco di altri libri. – mirod

3

Questo codice funziona anche:

$ perl -le 'my @a; $a[@a]="Hello"; $a[@a]=" world!"; print @a' 
Hello world! 

Perl matrice è dinamica e cresce quando assegnare oltre i limiti.

+0

Non vedo come ++ $ # array non lo cambierebbe. Suppongo che dopo l'assegnazione, $ # array venga nuovamente modificato, probabilmente con lo stesso valore. –

+0

Penso che '++ $ # array' sia inutile qui. –

+0

È necessario l'array ++ $ #, se si utilizza l'array $ # si sovrascrive semplicemente l'ultimo elemento dell'array (o si ottiene un errore di 'Modifica di valore di matrice non creabile, subscript -1' se l'array è vuoto) – mirod

1

Prima di tutto, è fallo.

Detto questo, sono anche sorpreso che funzioni. Avrei intuito che ++$#array avrebbe ottenuto l'errore "Impossibile modificare la costante" che si ottiene quando si tenta di incrementare un numero. (Non che io accidentalmente lo faccia, naturalmente.) Ma immagino che sia esattamente dove ci siamo sbagliati: $#array non è una costante (un numero); è un'espressione variabile. In quanto tale, puoi scherzare. Si consideri il seguente:

my @array = qw/1 2 3/; 

++$#array; 
$array[$#array] = qw/4/; 

print "@array\n" 

E anche, per il divertimento in più, in questo modo:

my @array = qw/1 2 3/; 

$#array += 5; 

foreach my $wtf (@array) { 
    if (defined $wtf) { 
    print "$wtf\n"; 
    } 
    else { 
    print "undef\n"; 
    } 
} 

E, sì, il Perl Cookbook è felice di pasticciare con $#array crescere o troncare array (Capitolo 4 , ricetta 3). Lo trovo ancora brutto, ma forse è solo un persistente "ma è un numero" di pregiudizi.

+0

Non sono sicuro di te ma * I * penso che sia brutto perché ha 4 simboli di punteggiatura, che non sono separatori o parentesi, in fila .... Voglio dire, ho anche cosa a = b + (foo? - $ # array: + $ # array); è brutto B-) –

+0

Anch'io ero sorpreso che funzionasse. –

4

Un post-incremento restituirà prima la variabile e quindi la incrementerà.

Se si è utilizzato il post-incremento, si modifica l'ultimo elemento, poiché viene restituito per primo e quindi si spinge un elemento vuoto alla fine.Nel secondo ciclo modificherete quel valore vuoto e ne spingerete uno nuovo dopo. Quindi non funzionerebbe affatto come una spinta.

Il pre-incremento incrementerà la variabile e quindi la restituirà. In questo modo il tuo esempio scriverà sempre su un nuovo, ultimo elemento dell'array e funzionerà come push. Esempio di seguito:

my (@pre, @post); 

$pre[$#pre++] = '1'; 
$pre[$#pre++] = '2'; 
$pre[$#pre++] = '3'; 


$post[++$#post] = '1'; 
$post[++$#post] = '2'; 
$post[++$#post] = '3'; 

print "pre keys: "[email protected]"\n"; 
print "pre: @pre\n"; 
print "post keys: "[email protected]"\n"; 
print "post: @post\n"; 

uscite:

pre keys: 3 
pre: 2 3 
post keys: 3 
post: 1 2 3 
+0

Il valore di "ritorno" dell'operatore di incremento è un'importante differenza, sono contento che qualcuno l'abbia fatto. – jettero

+1

@pre = (2, 3, undef); –