2015-08-20 7 views
8

Recentemente stavo cercando di fare un semplice round robin con Perl, e ho trovato un comportamento che non capisco chiaramente.Round robin di base in Perl differenza tra (++/+1)

Qui il comportamento:

my $a = {index => 0}; 
for (0 .. 10) { 
    $a->{index} = ($a->{index}++) % 2; 
    warn $a->{index}; 
} 

L'uscita di questo codice sarà:

0,0,0,..,0 

Ma se faccio lo "stesso" codice di sostituzione $ a -> {index} ++ da $ a -> {index} 1, il round robin andrà bene, ad esempio

my $a = {index => 0}; 
for (0 .. 10) { 
    $a->{index} = ($a->{index}+1) % 2; 
    warn $a->{index}; 
} 

l'output sarà:

1,0,1,0,1,0,1,0... 

Qualcuno può spiegarmi la differenza tra ++/+1 in questo caso? Lo trovo davvero "brutto", perché se non assegno il risultato a nessuna variabile nel caso "++" il codice funzionerà come previsto a meno che non inserisca la somma dentro().

Questo codice farà un round robin correttamente:

my $a = {index => 0}; 
for (0 .. 10) { 
    warn $a->{index}++ % 2; 
} 

Con() nella somma, il codice di uscita: 1,2,3,4,5,6,7,8,9

my $a = {index => 0}; 
for (0 .. 10) { 
    warn ($a->{index}++) % 2; 
} 
+0

Come su: '^ =' a 'xor'. Per esempio. 'if ($ x^= 1) {...' – Sobrique

+0

L'espressione '$ i = $ i ++' non cambierà il valore di '$ i' perché stai facendo l'assegnazione' $ i = $ i' prima del succede il dopo-incremento '++' Al contrario, l'espressione '$ i = $ i + 1' incrementerà' $ i' perché il lato destro '$ i + 1' viene valutato * prima * e viene assegnato a' $ i'. Credo che questo sia il punto cruciale dei tuoi problemi. – msw

risposta

10

$a->{index}+1 restituisce $a->{index}+1, mentre
$a->{index}++ rendimenti $a->{index} prima che fosse cambiato.
++$a->{index} restituisce $a->{index}+1, ma non ha senso utilizzarlo in quell'espressione poiché cambia inutilmente $a->{index}.


$a->{index} = ($a->{index}+1) % 2;

  1. Say $a->{index} è inizialmente 0.
  2. $a->{index}+1 restituisce 1.
  3. Quindi si assegna 1 % 2, che è 1 a $a->{index}.

$a->{index} = $a->{index}++ % 2;

  1. Say $a->{index} è inizialmente 0.
  2. $a->{index}++ set $a->{index} a 1 e restituisce 0 (il vecchio valore).
  3. Quindi si assegna 0 % 2, che è 0 a $a->{index}.

Opzioni:

$a->{index} = ($a->{index} + 1) % 2; 
if ($a->{index}) { 
    ... 
} 

o

$a->{index} = $a->{index} ? 0 : 1; 
if ($a->{index}) { 
    ... 
} 

o

$a->{index} = !$a->{index}; 
if ($a->{index}) { 
    ... 
} 

o

if (++$a->{index} % 2) { 
    ... 
} 

o

if ($a->{index}++ % 2) { 
    ... 
} 

notare che le ultime due opzioni lascia un valore sempre crescente in $a->{index} piuttosto che 0 o 1.

Si noti che le ultime due opzioni differiscono se la condizione sarà vera o falsa al primo passaggio.

+7

Una buona regola empirica è di non scrivere mai '$ var = ... ++ $ var ...' o '$ var = ... $ var ++ ...'. – cjm

+1

Possibile quarta opzione: '$ a -> {indice} =! $ A -> {indice}' Pro: meno brutto della prima opzione e meno rischio di overflow su ** lunghe ** attività in esecuzione rispetto alla 2a e 3a. Con: '''' vs. '0' (o' 2' o '4' ...) potrebbe essere importante nei contesti delle stringhe. – tjd

+0

Nel caso peggiore, fallirà solo dopo 2 ** 53 incrementi. Non ci sono stati molti microsecondi da quando unix è stato inventato nel 1970. – ikegami