> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/fi/syvalliset-artikkelit/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md).

# Miten \expandafter toimii: perusperiaatteista TeXin lähdekoodin tutkimiseen

[Osa 1](/latex/fi/syvalliset-artikkelit/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md) [Osa 2](/latex/fi/syvalliset-artikkelit/22-how-does-expandafter-work-the-meaning-of-expansion.md) [Osa 3](/latex/fi/syvalliset-artikkelit/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) [Osa 4](/latex/fi/syvalliset-artikkelit/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md) [Osa 5](/latex/fi/syvalliset-artikkelit/17-how-does-expandafter-work-a-detailed-macro-case-study.md) [Osa 6](/latex/fi/syvalliset-artikkelit/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)

## Johdanto

Olemme nyt käsitelleet taustateemat, joita tarvitaan perusteelliseen tarkasteluun aiheesta `\expandafter`:

* TeX-tokenien perusteet ja niiden laskentatapa;
* TeXin laajennusprosessin periaatteet;
* TeXin väliaikaisten token-listojen käyttö/lisääminen asiakirjaa käsiteltäessä;
* miten TeX käyttää ja “jongleeraa” useita syötelähteitä (mukaan lukien väliaikaiset token-listat).

Tässä artikkelissa yhdistämme nämä aiheet/käsitteet selittääksemme mekanismit, jotka ovat TeXin `\expandafter` komennon taustalla: lyhyesti, miten se toimii.

## Ja niinpä, \expandafter

Ajatus `\expandafter` takana on pakottaa komennon (tokenin) laajeneminen ennen kuin TeX normaalisti tekisi niin. Kun on kaksi tokenia, $$\mathrm{T\_1}$$ ja $$\mathrm{T\_2}$$ toiminta `\expandafter` $$\mathrm{T\_1T\_2}$$ johtaa siihen, että TeX käsittelee $$\mathrm{T\_1}\text{<}$$laajenemisen $$\mathrm{T\_2}\text{>}$$, jossa $$\text{<}\dots\text{>}$$ osoittaa token-listaa. TeX laajentaa $$\mathrm{T\_2}$$ ennenaikaisesti niin, että token $$\mathrm{T\_1}$$ (esim. primitiivi tai makro) pääsee näkemään tai voi toimia niiden tokenien perusteella, jotka syntyvät tokenin $$\mathrm{T\_2}$$laajenemisesta. Jos token $$\mathrm{T\_2}$$ edustaa ei-laajennettavaa kohdetta, kuten ei-aktiivista merkkiä tai useimpia primitiivejä, `\expandafter` toiminta $$\mathrm{T\_1T\_2}$$ ei muuta mitään: TeX jatkaisi tokenien käsittelyä

### Johdanto \expandafter:n käyttöön

Jos et ole käyttänyt `\expandafter`, tässä on esimerkki sen käytöstä primitiivin `\uppercase{...}`kanssa. Oletetaan, että haluaisimme ladella pää `.tex` syötetiedoston nimen, mutta suuraakkosilla. Saatamme tuntea seuraavat TeX:n primitiivikomennot:

* `\uppercase`: tekee juuri sen, mitä nimi lupaa, eli muuntaa merkkitokenit niiden suuraakkosvastineiksi (jos sellaisia on);
* `\jobname`: kuten olemme nähneet, laajenee antamaan pää `.tex` tiedostossa.

Jos TeX-tiedostomme nimi on `mycode.tex` voisimme kohtuudella odottaa `\uppercase{\jobname}` ladottavan `MYCODE`. Mutta ei, se latoo `mycode` pienaakkosina. Mikä meni “vikaan”?

Jos kirjoitamme `\uppercase` yleisen käytön muodossa

```
\uppercase{<token list>}
```

voimme sanoa, että `\uppercase` silmäilee `<token list>` -listaa ja toimii vain (muuttaa kirjainasua) *merkkitokenien* kohdalla, jotka se havaitsee `<token list>`: kaikki ei-merkkitokenit *ohitetaan* koska `\uppercase` ei “katso sisään” (laajenna) ei-merkkitokeneita nähdäkseen, mitä ne sisältävät tai edustavat. Koska token on vain kokonaislukuarvo, `\uppercase` täytyy vain käydä token-lista läpi tarkistaakseen, kuuluuko jokaisen tokenin numeerinen arvo `<token list>` alueeseen, joka ilmaisee merkkitokenin. Sattumoisin `\uppercase` myös *muuttaa aktiivisten merkkien kirjainasua* luodakseen suuraakkosisen aktiivisen merkin, jonka on edelleen oltava määritelty, muuten TeX tuottaa virheen: `Määrittelemätön ohjaussarja`, mutta poikkeamme aiheesta...

Esimerkiksi, vaikka määrittelisimme makron, joka on pelkkää tekstiä

```
\def\foo{some lower-case text}
```

niin `\uppercase{\foo}` latoisi silti `some lower-case text` eikä `SOME LOWER-CASE TEXT` kuten toivoisimme, yksinkertaisesti siksi, että `\uppercase` toiminta ei yritä selvittää, mitä `\foo` edustaa: se näkee `\foo` komentotokenina ja ohittaa sen, aivan kuten se teki tokenin `\jobname`.

### Miten voimme korjata tämän? \expandafter pelastaa tilanteen

Ladellaksemme tiedostonimen suuraakkosversion meidän täytyy muokata `\uppercase{\jobname}` pakottamalla TeX korvaamaan `\jobname` sen laajenemisella (merkki-tokenien sarjalla) *ennen kuin* `\uppercase` pääsee toimimaan. Taas kerran laajenemista käytetään poistamaan `\jobname` token (komento) ja korvaamaan se sen laajenemisen tuloksella (token-listalla, joka sisältää merkkitokeneita). Joten jos kirjoitamme

```
\uppercase\expandafter{\jobname}
```

niin se toimii: `MYCODE` ladottaisiin. Tapahtuu niin, että TeX alkaa käsitellä `\uppercase` ja tarkistaa heti pakollisen aloitusaaltosulkeen (`{`); kuitenkin TeX havaitsee `\expandafter` komennon, joka saa sen väliaikaisesti “siirtämään huomionsa” käsittelyyn `\expandafter{\jobname}`.

Jos vertaamme

`\expandafter` $$\mathrm{T\_1T\_2}$$

esimerkkiimme

`\expandafter{\jobname}`

voimme nähdä

* $$\mathrm{T\_1} =\space$$`{`<sub>token</sub>
* $$\mathrm{T\_2} =\space$$`\jobname`<sub>token</sub>

Missä `{`<sub>token</sub> ja `\jobname`<sub>token</sub> viittaavat TeXin laskemiin token-arvoihin — alaindeksimerkintää <sub>token</sub> käytetään muistuttamaan itseämme siitä, että TeX toimii kokonaislukutokenien maailmassa.

Kirjoittaminen `\uppercase\expandafter{\jobname}` toimii, koska pääpiirteissään (yksityiskohdat seuraavat), `\expandafter` saa TeXin suorittamaan seuraavat tehtävät:

1. lukea ja tallentaa avaus `{`<sub>token</sub>;
2. lukea seuraava token: `\jobname`<sub>token</sub>. TeX tunnistaa, että `\jobname`<sub>token</sub> edustaa laajennettavaa komentoa ja laajentaa sen. `\jobname`<sub>token</sub> korvataan sen laajenemisella — merkkitokenien sarjalla;
3. kun `\jobname` komento on laajennettu, TeX laittaa `{`$$\_\mathrm{token}$$ “takaisin syötteeseen” ja käyttää token-listaa, joka syntyy tokenin `\jobname` laajenemisesta, niin että TeX lukee `\uppercase{`<sub>token</sub>`<\jobname:n laajeneminen>`<sub>token-lista (merkkejä)</sub>`}`, ja tämä tuottaa haluamamme tuloksen.

Seuraava kaavio näyttää, miten TeX käsittelee `\uppercase\expandafter{\jobname}`—lue kuva alhaalta ja etene ylöspäin seuraten prosessin kulkua.

![Miten \expandafter toimii](/files/a5992624263718ece9040e237e6cc76e61a6a620)

Seuraavat huomiot selittävät käsittelyn eri vaiheet.

1. TeX alkaa käsitellä `\uppercase` ja tarkistaa pakollisen avausaaltosulkeen (`{`) mutta havaitsee `\expandafter` komento.
2. Jos vertaamme `\expandafter` $$\mathrm{T\_1T\_2}$$ syötteeseemme `\expandafter{\jobname}` voimme nähdä $$\mathrm{T\_1} =$$`{`<sub>token</sub> ja $$\mathrm{T\_2} =$$`\jobname`<sub>token</sub>. Huomaa, että käytämme tässä alaindeksiä <sub>token</sub> osoittamaan, että TeX käsittelee kokonaislukutokenien arvoja.
3. `\expandafter` lukee ja tallentaa väliaikaisesti `{`<sub>token</sub> tallentamalla kyseisen kokonaislukutokenin arvon sisäiseen muuttujaan. Myöhemmin TeX sijoittaa tokenin takaisin syötteeseen käsiteltyään `\jobname` komento.
4. `\expandafter` lukee seuraavan tokenin, `\jobname`<sub>token</sub>, ja laajentaa `\jobname` komento.
5. Laajeneminen `\jobname` luo väliaikaisen token-listan, joka sisältää merkkitokenien sarjan, joka edustaa `.tex` tiedostonimeä. Huomaa, että kaikki merkkitokenit, jotka `\jobname` tuottaa, lasketaan käyttäen kategoriakoodia 12.
6. Kun `\jobname` on laajennettu, TeX lisää takaisin talletetun tokenin vaiheessa 3 (`{`<sub>token</sub>) ja palauttaa sen syötteeseen. TeX tekee sen luomalla toisen token-listan, joka sisältää *yksittäisen* `{`<sub>token</sub>
7. TeX on nyt lopettanut käsittelyn `\expandafter`, jolloin syntyi kaksi token-listaa, jotka ovat valmiita käytettäviksi TeXin syötelähteinä. TeX palaa nyt käsittelemään `\uppercase` mutta on konfiguroinut syötteensä siten, että kaksi token-listaa, jotka `\expandafter` luotiin, toimivat tokenien lähteenä `\uppercase`—joka nyt näkee `\uppercase{`<sub>token</sub>`<\jobname:n laajeneminen>`<sub>token-lista (merkkejä)</sub>`}`. `\uppercase` näkee nyt merkkitokenien sarjan ja voi tuottaa haluamamme tuloksen.
8. Lukemisen jälkeen kaikki merkkitokenit, jotka `\jobname`tuottaa, TeX palaa hakemaan tokenit aiemmasta syötelähteestään (meidän `.tex` tiedostostamme), josta se lukee seuraavan tokenin: sulkevan `}` tarvitaan päättämään token-lista, jota käsitellään `\uppercase`.

### \expandafter ja sisäiset token-listat

Väliaikaiset token-listat ovat *keskeinen* osa `\expandafter`käsittelykäyttäytymistä: näiden token-listojen käytön ja olemassaolon ymmärtäminen voi auttaa selventämään, miten `\expandafter` saavuttaa tuloksensa, erityisesti kun yritetään kirjoittaa tai ymmärtää makroja, jotka käyttävät useita peräkkäisiä `\expandafter` komentoja saavuttaakseen monimutkaisempia tokeninkäsittelyn muotoja: `\expandafter\expandafter\expandafter...`

Toinen keskeinen osa `\expandafter`käyttäytymistä, erityisesti useiden peräkkäisten `\expandafter` komentojen yhteydessä, on *rekursion* käyttö (TeX-ohjelmiston sisällä itsessään) — aihe, jota tarkastelemme myöhemmin tässä artikkelissa.

Auttaaksemme edelleen ymmärtämään väliaikaisia token-listoja tarkastelemme vielä yhtä esimerkkiä `\expandafter`käsittelystä, tällä kertaa käyttäen `\the` komento.

#### \expandafter ja sisäiset token-listat: esimerkki 2

Tässä esimerkissä näemme, miten `\expandafter` voidaan käyttää vaikuttamaan token-rekisteriin tallennettuihin tokeneihin `\toks` komennon kautta. Tässä ovat käyttämämme TeX-primitiivit:

* `**\count** *rekisteri*=*numero*`: TeX:n primitiivi, jota käytetään arvon `*numero*` tallentamiseen TeXin sijaintiin `*rekisteri*`;
* `**\toks** *rekisteri*={*token-lista*}`: TeX:n primitiivi, jota käytetään tallentamaan `*token-lista*` token-rekisterin sijaintiin `*rekisteri*`—tallentaa tokenien sarjan myöhempää käyttöä varten;
* `**\the** *token*`: laajennettava TeX:n primitiivikomento, joka käsittelee `*token*`, vaikka tarkat tulokset riippuvat käsiteltävän `*token*` tokenin luonteesta. `\the` sillä on useita käyttötapoja: niihin kuuluu TeX-parametriin tai -muuttujaan (esim. rekisteriin) tallennetun arvon ladonta. Muita `\the` käyttötapoja ovat token-rekisteriin tallennettujen tokenien kopion lisääminen. Tässä käytämme `\the` ladellaksemme arvon, joka on tallennettu `\count` rekisteriin.

Aloitamme seuraavalla TeX-koodilla tallentaaksemme arvon `12345` TeXin `\count` rekisteriin `99`:

```
\count99=12345
```

Jos haluamme ladella arvon, joka on tallennettu `\count99` voimme käyttää `\the\count99` (tai `\number\count99`).

Seuraavaksi käytämme `\toks` komentoa tallentaaksemme joitakin tokeneita token-rekisteriin `99`:

```
\toks99={\the\count99 }
```

Token-rekisteriin `99` tallennettu token-lista sisältäisi seuraavat:

|                      |                                                                                                                     |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **TeX-tokenin arvo** | **Esitetty kohde**                                                                                                  |
| 5382                 | `\the`                                                                                                              |
| 7885                 | `\count`                                                                                                            |
| 3129                 | `9` (merkistökoodi 57 kategoriakoodilla 12), jolloin tokenin arvoksi tulee $$256 \times 12 + 57 = 3129$$            |
| 3129                 | `9` (merkistökoodi 57 kategoriakoodilla 12), jolloin tokenin arvoksi tulee $$256 \times 12 + 57 = 3129$$            |
| 2592                 | `<välilyönti>` (merkistökoodi 32 kategoriakoodilla 10), jolloin tokenin arvoksi tulee $$256 \times 10 + 32 = 2592$$ |

Huomaa, että token-lista, jonka `\toks99` ei *sisällä* varsinaista tietoa, joka on tallennettu `\count99` koska `\toks` komento ei suorita laajennusta: se vain luo tokenit ja tallentaa ne. Esimerkissämme `\the` ei laajennu, joten se ei käsittele `\count99`; tässä `\the` muunnetaan vain tokeniksi (arvo 5382) ja tallennetaan token-listaan.

Jos haluamme, että `\toks99` token-lista sisältää tokeneita, jotka edustavat tietoa, joka on tallennettu `\count99` meidän täytyy jotenkin luoda nuo tokenit (saada ne saataville), jotta `\toks` komento voi käyttää niitä. Ja tietenkin `\expandafter` voi tehdä tämän puolestamme. Jos kirjoitamme:

```
        \toks99=\expandafter{\the\count99 }
```

komennon toiminta/käsittely laitetaan “jäihin”, kun taas `\toks` saa aikaan (pakottaa) `\expandafter` laajenemisen `\the` joka puolestaan vaikuttaa `\count` luodakseen väliaikaisen token-listan, joka sisältää merkkitokenit, jotka edustavat tietoa, joka on tallennettu `\count99`. Pieni mutta tärkeä seikka on `<välilyönti>` numeroiden `99`jälkeinen `<välilyönti>` merkki: tämä merkki päättää TeXin skannausprosessin, kun se etsii numeerista arvoa.

Tässä `\expandafter` toiminta on hyvin samankaltainen kuin `\jobname` esimerkissä.

1. Lue ja tallenna avaus `{`<sub>token</sub>.
2. Lue seuraava token, `\the`<sub>token</sub>, joka edustaa laajennettavaa komentoa, joten TeX laajentaa sen. `\expandafter` pakottaa laajenemaan `\the` joka sitten toimii `\count99` muuntaakseen tiedon, joka on tallennettu `\count` rekisteriin `99` (luku 12345) väliaikaiseksi token-listaksi. Tämä lista sisältää merkkitokenit, jotka edustavat numeroita `1`, `2`, `3`, `4` ja `5`—kategoriakoodin 12 merkkitokenit.
3. Kun `\the`on laajennettu ja käsitelty, TeX laittaa `{`<sub>token</sub> “takaisin syötteeseen” ja käyttää token-listaa, joka syntyy `\the\count99` laajenemisesta, niin että TeX lukee `\toks99={`<sub>token</sub>`<\the\count99:n laajeneminen>`<sub>token-lista (merkkejä)</sub>`}` ja tämä tuottaa haluamamme tuloksen.

Tämä tapahtumasarja on koottu seuraavaan kaavioon — lue kuva alhaalta ja etene ylöspäin seuraten prosessin kulkua.

![Miten \expandafter toimii](/files/7dd91282cc2d0fd4782cc3de60b46099904761ca)

1. TeX alkaa käsitellä `\toks`; se näkee valinnaisen `=` merkin, tarkistaa sitten pakollisen avausaaltosulkeen (`{`, tai minkä tahansa merkin, jonka kategoriakoodi on 1) ja jota käytetään token-listan alun osoittamiseen. TeX kuitenkin havaitsee `\expandafter` komennon ja jatkaa suorittamalla sitä sen sijaan.
2. Jos vertaamme `\expandafter` $$\mathrm{T\_1T\_2}$$ syötteeseemme `\expandafter{\the\count99 }` voimme nähdä $$\mathrm{T\_1} =$$ `{`<sub>token</sub> ja $$\mathrm{T\_2} =$$ `\the<sub>token</sub>`.
3. `\expandafter` lukee ja tallentaa väliaikaisesti `{`<sub>token</sub> (TeX tallentaa kyseisen kokonaislukutokenin arvon väliaikaisesti sisäiseen muuttujaan). Myöhemmin TeX lisää tokenin takaisin syötteeseen käsiteltyään `\the`
4. `\expandafter` lukee seuraavan tokenin, `\the`<sub>token</sub> ja laajentaa sen.
5. Laajeneminen `\the` luo väliaikaisen token-listan käsittelemällä `\count99`—token-lista sisältää merkkitokenien sarjan, joka edustaa tietoa, joka on tallennettu `\count` rekisteriin `99`.
6. Kun `\the` on laajennettu, TeX lisää takaisin talletetun tokenin vaiheessa 3 (`{`<sub>token</sub>) ja laittaa kyseisen tokenin takaisin syötteeseen. TeX tekee sen luomalla toisen token-listan, joka sisältää *yksittäisen* token `{`<sub>token</sub>.
7. TeX on nyt lopettanut käsittelyn `\expandafter` ja tuotti kaksi token-listaa, jotka ovat valmiita käytettäviksi seuraavina syötelähteinä. TeX palaa takaisin käsittelemään `\toks99=` mutta nyt TeX on konfiguroinut syötteensä niin, että kaksi token-listaa, jotka `\expandafter` luotiin, toimivat tokenien lähteenä `\toks`—joka nyt näkee `{`<sub>token</sub>`<\the\count99:n laajeneminen>`<sub>token-lista (merkkejä)</sub>`}`. `\toks` voivat nyt käyttää ja tallentaa 5 merkkitokenin sarjan, joka edustaa tietoa-arvoa (`12345`) joka on tallennettu `\count99`: haluamamme tulos.
8. Kun kaikki merkkitokenit, jotka `\the\count99`tuottaa, TeX palaa hakemaan tokenit aiemmasta syötelähteestään (meidän `.tex` tiedostostamme), josta se lukee seuraavan tokenin: sulkevan `}` tuottivat, on luettu, TeX palaa tokenien käsittelyyn, jotka on tarkoitus tallentaa `\toks99={...}`.

## Miten \expandafter todella toimii

Tässä osiossa tarkastelemme TeXin sisäistä toimintaa “alhaisella tasolla”: tutkien TeXin lähdekoodia/funktioita, jotka toteuttavat `\expandafter`käyttäytymisen. Yksityiskohdat on ilmaistu pseudo-C-koodina, mutta niiden pitäisi olla ymmärrettäviä kenelle tahansa, joka tuntee muita ohjelmointikieliä.

Seuraava selitetty kaavio selittää, miten TeX toteuttaa `\expandafter` osana suurempaa funktiota nimeltä `expand()`—ydinfunktiona, joka ohjaa TeXin laajennuskäsittelyä. Osassa, joka vastaa `\expandafter` voimme nähdä [*rekursiivista* käyttäytymistä,](https://en.wikipedia.org/wiki/Recursion) jossa toinen kutsu `expand()` funktioon käytetään käsittelemään toinen luettu token, $$\mathrm{T\_2}$$, niissä tapauksissa, joissa $$\mathrm{T\_2}$$ on laajennettava.

Vaikka tämä koodi esiintyy Knuthin TeX-moottorissa, tämän kaavion esittämät perusperiaatteet pätevät kaikkiin TeX-moottoreihin.

![Miten \expandafter toimii TeXin sisällä](/files/0a2915f42c7b33798b3c3b377306567d3a122107)

Ensimmäinen tehtävä `expand()` on määrittää, onko laajennettava komento makro vai primitiivi, koska makroilla on erikoistunut laajennusprosessi, jota käsittelee funktio nimeltä `macrocall()`.

Jos laajennettava komento on primitiivi, `expand()` funktio käyttää nykyistä komentokoodin arvoa (tallennettu globaalimuuttujaan `curcmd`) tunnistaakseen, mikä tietty primitiivi on käsiteltävä. Näemme nämä yksityiskohdat täydellisemmässä luettelossa `expand()`:

```
    void expand(void)
    {
    //curcmd on globaalimuuttuja
    if(curcmd != macro) // curcmd < 111
    {
      switch(curcmd)
      {
        case \expandafter: // Käsittele \expandafter T1T2 -komento
        {
            gettoken(); // Lue tunnus T1
            t = curtok; // Tallenna tunnus T1 paikalliseen muuttujaan t
            gettoken(); // Lue tunnus T2
            if(curcmd > 100) // Onko tunnus T2 laajennettavissa?
                expand();    // Kyllä! T2 on laajennettavissa:
                             // suorita T2:n laajennus käyttäen
                             // tekemällä rekursiivinen funktiokutsu funktiolle expand()
            else
                backinput(); // T2 ei ole laajennettavissa: laita tuo tunnus
                             // takaisin syötteeseen, jotta se luetaan uudelleen (myöhemmin)

            curtok = t ;  // Palauta globaali muuttuja curtok tallennettuun T1:n arvoon
            backinput() ; // Laita tunnus T1 takaisin syötteeseen
                          // ennen T2:n laajennuksesta syntyviä tunnuksia
        }
        break;

        // Koodi muiden laajennettavien komentojen käsittelyyn
        case “convert to text” command: // Mikä tahansa seuraavista: \number, \string, \romannumeral,
                                        // \meaning, \fontname, \jobname
                                        // Niillä on sama curcmd-arvo
        break;

        case \noexpand: // Estä seuraavan tunnuksen laajentaminen
        ...
        break;

        case \csname:  // Muodosta ohjaussekvenssin nimi.
        ...
        break;

        case \the: // Lisää joitakin tunnuksia
        ....
        break;

        case “\if... test command” : // Käsittele yksi TeXin ehtokomennosta:
                                      // \if, \ifcat, \ifnum, \ifdim,\ifodd, \ifvmode,
                                      // \ifhmode, \ifmmode, \ifinner, \ifvoid,
                                      // \ifhbox, \ifvbox, \ifx, \ifeof, \iftrue, \iffalse,
                                      // \ifcase, \ifdefined, \ifcsname, \iffontchar
        ...
        break;

        case “\fi or \else”: // Lopeta nykyinen ehtolause
        ...
        break;

        // jne. kaikille muille laajennettaville peruskomentoille, joita
        // TeX-moottori tukee

        }

    }else // Ei laajennettava peruskomento: se on makro
        {
             macrocall()
        }
        //... lisää koodia poistettu
    }
```

### TeXin rakkaus globaaleihin muuttujiin

Ehkä heijastaen sen ikää ja aikaa, jolloin se suunniteltiin, TeXin lähdekoodi käyttää runsaasti niin sanottuja [globaaleja muuttujia](https://en.wikipedia.org/wiki/Global_variable)—itse asiassa niitä on satoja. Globaaleja muuttujia voidaan luonteensa vuoksi muuttaa/muokata mistä tahansa TeXin lähdekoodin kohdasta, mikä Knuthin TeXissä on yksi monoliittinen tiedosto, joka sisältää yli 25 000 riviä koodia ja satoja funktioita. TeXin toiminnan ymmärtäminen ei ole aina helppo tehtävä...

Käsitelläkseen `\expandafter`, TeX lukee tunnuksia nykyisestä syötteestään käyttäen funktiota nimeltä `gettoken()` jonka tehtävänä on luoda tunnus ja asettaa useiden keskeisten globaalien muuttujien arvo, joita käytetään kautta TeXin lähdekoodin. Kaksi tällaista muuttujaa, joita päivittää `gettoken()`, käytetään toteutuksessa seuraaville: `\expandafter`:

* `curtok`: (nykyinen tunnus) juuri luetun tunnuksen kokonaislukuarvo;
* `curcmd`: (nykyinen komentoarvo) komennon (tai merkin) komentoarvo, jota tunnus edustaa `curtok`.

Käsiteltäessä `\expandafter`$$\mathrm{T\_1T\_2}$$ TeX lukee tunnuksen $$\mathrm{T\_1}$$ ja tallentaa sen arvon väliaikaisesti paikalliseen muuttujaan nimeltä `t`. TeX lukee sitten $$\mathrm{T\_2}$$ ja tarkistaa, edustaako tuo tunnus laajennettavaa komentoa — tarkistamalla onko sen komentoarvo (`curcmd`) > 100. Jos on, TeX:n täytyy laajentaa $$\mathrm{T\_2}$$ :llä edustettua komentoa `expand()`: tämä on esimerkki siitä, että *rekursion* koska `expand()` funktio kutsuu itseään. Rekursiivisen laajennuksen luonteen ymmärtäminen, erityisesti käytettäessä `\expandafter`, voi auttaa ymmärtämään, kuinka useat peräkkäiset `\expandafter` komennot — eli `\expandafter\expandafter\expandafter...` saavat aikaan vaikutuksensa.

Jos tunnus $$\mathrm{T\_2}$$ on laajennettavissa, laajennus suoritetaan ja kun rekursiivinen kutsu funktioon `expand()` palauttaa arvon, koodi sisällä `\expandafter` tunnuksen $$\mathrm{T\_1}$$ takaisin syötteeseen. Globaali muuttuja `curtok` saa uudelleen arvon tallennetusta tunnuksesta — joka on tallennettu paikalliseen muuttujaan `t`, joka on tunnuksen $$\mathrm{T\_1}$$arvo — ja tehdään kutsu funktioon `backinput().`

#### Funktio backinput()

Kuten nimi vihjaa, tämä funktio laittaa tunnuksen “takaisin syötteeseen”. TeX käyttää siihen nykyistä arvoa globaalista muuttujasta `curtok` luodakseen tunnuslistan, joka sisältää yhden tunnuksen (jonka kokonaislukuarvon antaa `curtok`). TeX järjestää myös syötteenkäsittelynsä niin, että tuo yhden tunnuksen lista luetaan sopivalla hetkellä uudelleen TeXissä osana myöhempää syötteenkäsittelyä. Huomaa tarkasti, että tunnus $$\mathrm{T\_1}$$ lisätään uudelleen *kun laajennus on valmis*, mikä varmistaa, että TeX lukee tuon uudelleen lisätyn tunnuksen *ennen kuin* kun se lukee tunnuksia, jotka syntyvät $$\mathrm{T\_2}$$.

### Makrojen käsittely: macrocall()-funktio

Kuten aiemmin käsiteltiin, kaikki makrot sekä jotkin peruskomennot ovat laajennettavia, ja kaikki laajennuskäsittely kulkee `expand()` -funktion kautta. Kuitenkin, `expand()` käyttää huolellisesti `curcmd` (nykyinen komento) -arvoa erottaakseen laajennettavat peruskomennot ja makrot, koska makron laajennusprosessi käsitellään sitä varten omistetulla funktiolla nimeltä `macrocall()`. Makrot tarvitsevat erikoistuneen laajennusprosessin, koska makroargumentit ja erotustunnukset on etsittävä hyvin erityisellä ja tarkalla tavalla; siksi tuo prosessi annetaan funktiolle, joka on suunniteltu juuri siihen: `macrocall()`.

#### Makron laajennus vs. makron suoritus

Makron *laajennus* ei ole sama prosessi kuin makron *suoritus*: makron laajennus on esisuorituksen vaihe, jonka TeX tekee saadakseen makron *valmiiksi suoritettavaksi*. Makron “suoritus” tapahtuu, kun TeX lukee ja käsittelee aktiivisesti kyseisen makron määrittelyssä (korvaustekstissä) ja sen argumenteissa (parametreissa) olevia tunnuksia.

#### Makron laajennus

Makron laajentamiseksi TeX tarkistaa ensin, ottaako makro argumentteja; jos ottaa, `macrocall()` se käy hyvin tarkasti läpi syötteen etsien tunnuksia, joista on määrä tulla makron argumentteja. Tähän prosessiin kuuluu käyttäjän syötteen tarkistaminen sellaisten erotustunnusten varalta, joita käytettiin makron alkuperäisessä määrittelyssä — makrokutsussa käytettyjen tunnusten kuvion täytyy täsmälleen vastata tallennettuun määrittelyyn sisältyvien tunnusten kuviota. Tunnukset, joita käytetään erotustunnuksina, TeX kuitenkin yksinkertaisesti hylkää: ne ovat käytännössä vain eräänlaista “välimerkistöä”, jota TeX käyttää määrittääkseen varsinaiset tunnukset, joiden on määrä tulla makron argumenteiksi — eli tunnukset, jotka käyttäjä tarkoittaa makron käsiteltäviksi. Lisätietoja erotustunnuksista on kohdassa [Miten TeX-makrot todella toimivat?](/latex/fi/lisaa-aiheita/22-how-tex-macros-actually-work-part-4.md).

Jokaisen parametrin (`#1, #2...#9`) kohdalla, joka on läsnä makron alkuperäisessä määrittelyssä, TeX käy läpi varsinaisen makrokutsun tunnistaakseen, mitkä käyttäjän antamat tunnukset on tarkoitettu kullekin parametrille (eli muodostavat makron argumentit). Tämä prosessi tuottaa yhden tai useamman pienen tunnuslistan: yhden jokaista makroargumenttia kohden.

Kun mahdolliset makroargumentit on tunnistettu ja niiden tunnuslistat valmisteltu, TeX hakee muistissaan talletetun makron määritelmän (korvaustekstin) ja järjestää syötteenkäsittelynsä siten, että aina kun TeX on valmis lukemaan/käsittelemään lisää tunnuksia, se lukee ne makron korvaustekstistä, jolloin makro suoritetaan. Sopivassa kohdassa makron suorituksen aikana makroargumentteja edustavat tunnuslistat syötetään oikeaan kohtaan makron korvaustekstissä.

Jälleen kerran makrokäskyn laajennus tarkoittaa *poistamista* tuon makrokäskyn (tunnuksen) syötteestä ja *korvaamista* sillä tunnuslistalla, joka on tallennettu makron korvaustekstiksi.

Syvällinen katsaus TeXin makrokäsittelyyn löytyy kuusiosaisesta artikkelisarjasta [Miten TeX-makrot todella toimivat?](/latex/fi/lisaa-aiheita/01-a-six-part-series-how-do-tex-macros-actually-work.md)

[Osa 1](/latex/fi/syvalliset-artikkelit/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md) [Osa 2](/latex/fi/syvalliset-artikkelit/22-how-does-expandafter-work-the-meaning-of-expansion.md) [Osa 3](/latex/fi/syvalliset-artikkelit/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) [Osa 4](/latex/fi/syvalliset-artikkelit/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md) [Osa 5](/latex/fi/syvalliset-artikkelit/17-how-does-expandafter-work-a-detailed-macro-case-study.md) [Osa 6](/latex/fi/syvalliset-artikkelit/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/fi/syvalliset-artikkelit/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
