**Toistorakenne** eli **silmukka** on ohjelmointikielten rakenne, joka toistaa annettua ohjelmakoodia, kunnes annettu ehtolause ei enää evaluoidu todeksi. Toistorakenteen sisältämää lohkoa voidaan toistaa tietyn määrän kertoja, kerran jokaiselle kokoelman jäsenelle, kunnes jokin ehto on täytetty tai määräämättömäksi ajaksi. Silmukat ovat kätevä työkalu ohjelmoinnissa, sillä niillä voidaan toistaa automaattisesti tiettyä komentoa tarvittavan monta kertaa vaivatta.

Useat ohjelmointikielet tukevat eri muotoja, mutta eivät välttämättä jokaista muotoa. Sivunkuvauskielet kuten HTML ja kyselykielet kuten SQL eivät yleensä tue toistorakenteita.

While-rakenne
-------------

`while`- rakenteessa ehtolause tarkistetaan jo ennen lohkon suorittamista ja tästä syystä tämä ohjausrakenne tunnetaan usein myös nimellä **pre-test loop** (karkeasti käännettynä: esitestisilmukka).

Java-kielessä, C-kielessä ja C++ -kielessä `while`-silmukka kirjoitetaan seuraavasti:

```
while (toistoehto) {
 /\* toistettava ohjelmakoodi \*/
}

```

Python-kielessä taas seuraavasti:

```
while (toistoehto):
    #toistettava ohjelmakoodi

```

Python-kielessä ei ole erillisiä silmukan alku- eikä loppumerkkejä. Siksi sisennys eli rivien alussa olevat välilyönnit ovat erityisen tärkeitä.

Ruby-kielessä on `until`-rakenne, joka on käänteinen `while`-rakenteelle: lausekkeen ollessa tosi ja tämän vastakohtana lausekkeen ollessa epätosi.

Do-while-silmukka
-----------------

`do-while`-silmukka eroaa `while` -silmukasta siinä, että toistoehdon tarkastus tehdään vasta silmukan rungon suorittamisen jälkeen, jolloin annettu runko tulee aina suoritetuksi vähintään kerran. Koska `do-while`-silmukka tarkistaa toistoehdon vasta rungon suorittamisen jälkeen, tunnetaan tämä ohjausrakenne myös nimellä **post-test loop** (karkeasti käännettynä: testin jälkeinen silmukka).

```
do {
 /\* toistettava koodi \*/
} while (toistoehto);

```

For-silmukka
------------

`for`-silmukka on samankaltainen kuin `while`, mutta sen arvot voidaan alustaa suoraan argumenteissa. `for`-silmukka toimii suorittamalla koodin osan toistuvasti kunnes tietty ehto on täytetty. Esimerkiksi Python-kielessä `for`-silmukkaan voidaan myös yhdistää `range` - komento jolloin muuttuja käy läpi haluttuja lukuja. Silmukan määrittelyssä annetaan kolmessa kohdassa alustustoimenpiteet, tarkistusehdot ja toiston jälkeen suoritettava toiminto, joita voi kielestä riippuen olla useita joka kohdassa. Tavanomainen määrittely näyttää samanlaiselta C, C++ ja Java kielissä:

```
for (int i = 0; i < 10; i++) {
    //toistettava koodi
}

```

Ehtoja voidaan yhdistää eri kentissä seuraavasti:

```
int a, b;
for (a = 0, b = 9; a < 10 && b >= 0; a++, --b)
{
 printf("a: %d, b: %d\n", a, b);
}

```

Foreach-silmukka
----------------

`foreach`-silmukka toistaa silmukan runkoa, kunnes jokainen annetun kokoelman tietue on käsitelty. Foreach-rakenne piilottaa viittauksen taulukon indeksiin tai vastaavaan käsittelyn kannalta epäoleelliseen tietoon. Kokoelman on oltava yhteensopiva foreach-rakenteen kanssa (esim. Javan Collection, Rubyn enumerable). `foreach`-silmukkaa käytetään usein `for`-silmukan sijaan aika samalla tavalla. Eroavaisuutena `foreach`-silmukan ja muiden `for`-rakenteiden välillä on se, että `foreach`-silmukka ei yleensä sisällä mitään eksplisiittistä laskuria. Tämän silmukan toiminta on enemmän: "tee tämä kaikille tässä kokoelmassa", entä "tee tämä x monta kertaa".

Seuraava Java-kielinen esimerkkiohjelma laskee kokonaislukutaulukon alkioiden summan - Javassa avainsana on ei ole `foreach`, vaan `for`:

```
int sum(int[] a) {
    int result = 0;
    for (int i : a)
        result += i;
    return result;
}

```

Python:

```
#Luodaan lista.
lista = ["1. arvo", "2. arvo", "3. arvo"]
#silmukka:
for x in lista:
            print (x);

```

C++ tukee `foreach`-silmukkaa C++11:stä lähtien rajatun alueen `for`-silmukkana (engl. *range-based for loop*):

```
#include <iostream>

int main()
{
 int myint[] = {1, 2, 3, 4, 5};

 for (int i : myint)
 {
 std::cout << i << '\n';
 }
}

```

Toistorakenteet kääntäjissä
---------------------------

Ohjelmointikielen kääntäjät voivat suorittaa erilaisia optimointeja, joissa suoritusaikaa pienennetään. Esimerkkeinä toistorakenteen *purkaminen* (engl. *unrolling*).

Katso myös
----------

* Ikuinen silmukka

#### Englanninkielisiä artikkeleita aiheesta

* en:While loop
* en:Do while loop
* en:For loop
* en:Foreach loop

Lähteet
-------

1. ↑   (Arkistoitu – Internet Archive)
2. ↑  Public Instance Methods *ruby-doc.org*. Viitattu 18.6.2022. (englanniksi)
3. ↑  Loop Optimizations: how does the compiler do it? *johnysswlab.com*.  19.9.2021. Viitattu 19.6.2022. (englanniksi)