2015-08-20 10 views
8

Ostatnio próbowałem zrobić prosty round robin z Perlem i znalazłem zachowanie, którego nie rozumiem jasno.Basic round robin w Perlu różnica między (++/+1)

Tutaj zachowanie:

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

Wyjście z tego kodu będzie:

0,0,0,..,0 

Ale jeśli to zrobię "ten sam" kod zastępując $ a -> {index} ++ przez $ a -> {index} +1, okrągłe robin będzie dobrze, przykład

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

wyjście będzie:

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

Ktoś może mi wyjaśnić różnicę między ++/+1 w tym przypadku? Uważam, że jest to naprawdę "brzydkie", ponieważ jeśli nie przypiszemy wyniku do żadnej zmiennej w przypadku "++", kod będzie działał zgodnie z oczekiwaniami, chyba że wstawię sumę do środka().

ten kod zrobi karuzeli poprawnie:

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

with() w sumie, kod wyświetli: 1,2,3,4,5,6,7,8,9

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

Co powiecie: '^ =' na 'xor'. Na przykład. 'if ($ x^= 1) {...' – Sobrique

+0

Wyrażenie '$ i = $ i ++' nie zmieni wartości '$ i', ponieważ wykonujesz przypisanie' $ i = $ i' przed ma miejsce post-inkrementacja '++'. W przeciwnym razie wyrażenie '$ i = $ i + 1 'zwiększy wartość' $ i', ponieważ prawy bok '$ i + 1' jest obliczany * pierwszy * i zostaje przypisany do' $ i'. Wierzę, że to jest sedno twoich problemów. – msw

Odpowiedz

10

$a->{index}+1 zwraca $a->{index}+1, natomiast
$a->{index}++ powraca $a->{index} zanim został zmieniony.
++$a->{index} zwraca $a->{index}+1, ale nie ma sensu używać go w tym wyrażeniu, ponieważ niepotrzebnie zmienia się $a->{index}.


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

  1. Say $a->{index} początkowo 0.
  2. $a->{index}+1 zwraca 1.
  3. Następnie przypisujesz 1 % 2, czyli 1 do $a->{index}.

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

  1. Say $a->{index} początkowo 0.
  2. $a->{index}++ ustawia $a->{index} na 1 i zwraca 0 (stara wartość).
  3. Następnie należy przypisać 0 % 2, czyli 0 do $a->{index}.

Opcje:

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

lub

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

lub

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

lub

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

lub

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

Zauważ, że dwie ostatnie opcje pozostawia coraz większą wartość w $a->{index} zamiast 0 lub 1.

Należy pamiętać, że dwie ostatnie opcje różnią się tym, czy warunek będzie prawdziwy, czy fałszywy w pierwszym przebiegu.

+7

Dobrą zasadą jest nigdy nie pisać '$ var = ... ++ $ var ...' lub '$ var = ... $ var ++ ...'. – cjm

+1

Możliwe 4 opcje: '$ a -> {indeks} =! $ A -> {indeks}' Plusy: mniej brzydka niż pierwsza opcja i mniejsze ryzyko przepełnienia ** długich ** zadań bieżących niż 2 i 3. Con: '' '' '0 '(lub' 2' lub '4' ...) może być ważne w kontekście łańcucha znaków. – tjd

+0

W najgorszym przypadku zakończy się niepowodzeniem po 2 ** 53 krokach. Nie było tylu mikrosekund, odkąd unix został wynaleziony w 1970 roku. – ikegami

Powiązane problemy