> 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/lisaa-aiheita/24-how-tex-macros-actually-work-part-6.md).

# Miten TeX-makrot oikeastaan toimivat: osa 6

[Osa 1](/latex/fi/lisaa-aiheita/19-how-tex-macros-actually-work-part-1.md) [Osa 2](/latex/fi/lisaa-aiheita/20-how-tex-macros-actually-work-part-2.md) [Osa 3](/latex/fi/lisaa-aiheita/21-how-tex-macros-actually-work-part-3.md) [Osa 4](/latex/fi/lisaa-aiheita/22-how-tex-macros-actually-work-part-4.md) [Osa 5](/latex/fi/lisaa-aiheita/23-how-tex-macros-actually-work-part-5.md) [Osa 6](/latex/fi/lisaa-aiheita/24-how-tex-macros-actually-work-part-6.md)

## Johdanto ja yleiskatsaus: tarina tähän asti

Tämän sarjan edellisissä viidessä osassa olemme nähneet:

* miten TeX lukee syöttötiedoston merkit ja käyttää kategoriakoodeja tunnistaakseen eri merkkien “luokat” ja muuntaakseen ne sitten merkkitokeneiksi ja komentotokeneiksi;
* että makro koostuu käytännössä neljästä osasta:

```
<TeX-makron primitiivi><makron nimi><parametriteksti>{<korvausteksti>}
```

jossa:

* `<TeX-makron primitiivi>` = yksi seuraavista `\def`, `\edef`, `\gdef` tai `\xdef`;
* `<makron nimi>`= makrasi nimi, kuten `\foo`;
* `<parametriteksti>` voi olla “tyhjä” (ei läsnä) tai se voi olla merkkijono erotintokeneita ja makron parametrimerkkejä;
* `<korvausteksti>` on makrosi varsinainen runko: osa, joka “suoritetaan” (laajennetaan), kun kutsut makroa.
* miten `<parametriteksti>` osa voi sisältää laajan valikoiman tokeneita ja että TeX käyttää tätä osaa “tokenimallina” sovittaakseen makrokutsun sen alkuperäiseen määritelmään ja päätelläkseen makron kanssa käytetyt argumentit — ja miten TeX odottaa makron käyttötapasi vastaavan sen alkuperäistä määritelmää;
* että TeXissä makromääritelmä tallennetaan jatkuvana tokenien sarjana, joka edustaa `<parametriteksti>` ja `<korvausteksti>` osia.

Kun käytät makrokomentoa, TeX tarkistaa ensin, ottaako se parametreja. Jos ottaa, TeX:n on sitten tunnistettava varsinaiset *argumentit* jotka käytetään makrokutsussasi. TeX:n on testattava makrokutsuaan muistissa tallentamaansa “tokenimalli”-määritelmää vasten. Tarkemmin sanottuna TeX käyttää makrosi sisäistä (tallennettua) määritelmää `<parametriteksti>` osaa mallina, jonka avulla se voi poimia *tokenit* jotka ovat varsinaisia argumentteja, ja jotka *tokenit* ovat vain erotinmerkkejä.

## Makrolaajennuksen merkitys

Olemme nyt vihdoin valmiita siirtymään tärkeimpään aiheeseen: miten TeX käsittelee makroargumentteja ja suorittaa makron itse asiassa: prosessi, johon TeX viittaa nimellä *makrolaajennus*.

### Mutta ensin lyhyt esimerkki: jotain outoa?

Jotta voimme “luoda lähtöasetelman” selittäessämme mekanismia, jolla TeX käsittelee makroja ja niiden argumentteja, käytämme lyhyttä esimerkkiä havainnollistamaan huomioon otettavia seikkoja.

#### Argumentit muunnetaan ensin tokeneiksi

Seuraava esimerkki perustuu esimerkkiin, jota käsitellään teoksen sivuilla 114–5 [The Advanced TeXbook](https://www.amazon.co.uk/Advanced-Texbook-David-Salomon/dp/0387945563) jonka on kirjoittanut David Salomon. Se on valittu, koska se tiivistää keskeiset ideat hyvin lyhyeen TeX-makroon.

Tavanomaisessa TeX/LaTeX-toiminnassa, `$` merkillä on kategoriakoodi 3 (“math shift”), joka kytkee TeXin sisään/ulos rivitysmatematiikkatilasta (`$...$`) tai esitysmatematiikkatilasta (`$$...$$`)—luonnollisesti LaTeX käyttää `\(..\)` ja `\[..\]` samoihin tarkoituksiin.

Oletetaan, että haluamme makron, joka muuttaa `$` merkin kategoriakoodiksi esimerkiksi 11:n, jotta voimme ladella sen kuten minkä tahansa tavallisen merkin. Voimme käyttää TeXin primitiivikomentoa `\catcode` ja ensimmäinen yrityksemme tällaiseksi makroksi, `\docat`, voisi olla

```
\def\docat #1{\catcode`\$=11 #1}
```

Kuitenkin, kun yritämme käyttää sitä näin

```
\begin{document}
\def\docat #1{\catcode`\$=11 #1}
I paid \docat{$90} for that book.
\end{document}
```

odotamme TeXin ladelleen `I paid $90 for that book.` mutta se epäonnistuu virheilmoituksella:

```
! Missing $ inserted.
<inserted text>
                $
<luetaan uudelleen>
                   \par
l.7
```

Virheestä näyttää siltä, että `$` makromme argumentissa käytetty merkki laukaisee yhä TeXin ladella matematiikkaa; selvästi TeX *ei* muuttanut `$` makromme argumentissa käytetyn merkin (`$90`). Kysymys kuuluu *miksi* miksi TeX ei muuttanut merkin `$` kategoriakoodiksi 11 ja ladellut sitä tavallisena merkkinä? Lyhyt vastaus on, että TeX muuntaa ensin makroargumentit tokeneiksi **ennen kuin** ja syöttää ne `<korvausteksti>`—mutta tarkastelemme taustalla olevia mekanismeja paljon yksityiskohtaisemmin.

On muistettava, että käsityksemme siitä, että TeX käyttää tekstiä/merkkejä, koskee vain sitä tiedoston sisältöä, jota TeX lukee: heti kun TeX on lukenut sisään yhtään merkkiä, olemme tokenien maailmassa *tokenit*. TeX-makrokutsut toimivat *tokenit*, eivät varsinaisten *kirjoitettujen/tekstuaalisten esitysten* TeX/LaTeX-komennoista — tämä selkenee, kun käymme esimerkin läpi.

Aluksi saatamme ajatella, että käyttämämme `\docat` makro kohdassa `I paid \docat{$90} for that book.` on sama kuin kirjoittaa suoraan vastaava TeX- (tai LaTeX-)koodi — kuten seuraava, joka *ei* toimii:

```
\begin{document}
I paid \catcode`\$=11 $90 for that book.
\end{document}
```

![Jotakin TeX-koodia käynnissä Overleafissa](/files/38491accdcec984d76ce2f0705565b0ffb400a8d)

Kuitenkin, kuten yllä näimme, tapa, jolla TeX käsittelee makroargumentteja, tuottaa tuloksen (`! Missing $ inserted.`) joka eroaa varsin paljon TeX-koodin kirjoittamisesta: nyt tutkimme *miksi* miten näin tapahtuu.

### Makrot ja argumentit tokenilistoina

Ymmärtääksemme täysin `\docat` makron ja sen argumentin (`$90`), ja miksi se epäonnistuu, meidän täytyy jälleen hahmottaa `\docat` makron määritelmä ja kaikki käytetyt argumentit (kun \docat kutsutaan)  *tokenilistoina*, ei merkkijonona.

Kun TeX käy läpi syötetäsi, se tunnistaisi `\docat` makrokomennoksi; sen jälkeen se tarkistaa, ottaako se parametreja — miten TeX tekee tämän, selitetään seuraavassa osiossa niille lukijoille, joita yksityiskohdat kiinnostavat.

#### Niille, jotka pitävät yksityiskohdista...

Kun makro on kutsuttu, TeX tarkistaa, onko aivan ensimmäinen tokeni (makron tallennetussa määrittelytokenilistassa) **lopetussovitus** tokeni: jos on, TeX voi olla varma, ettei makro ota parametreja.

**Esimerkki**

Seuraavat solmulistakaaviot vertaavat kahden makron tokenilistoja:

* `\def\foo A#1B{#1}`: tässä on `<parametriteksti>` kohteelle `A#1B`, joten **lopetussovitus** tokeni on **sisällä** ensimmäinen tokeni, joten TeX jatkaisi parametrien etsimistä;
* `\def\foo{X}`: tässä ei ole `<parametriteksti>` osaa, joten **lopetussovitus** tokeni on tokenilistan ensimmäinen ja TeX tietää, ettei sen pidä etsiä parametreja.

![Miten TeX tarkistaa, ottaako makro parametreja](/files/4975bfb5c904750c073e93a538388f84fcb69b27)

## Kohti “suurta finaalia”: laajennus

Palataan kysymykseen: miksi seuraava makro ei toiminut; toisin sanoen, miksi TeX ei muuta minkään `$` merkin kategoriakoodia, joka on käytetty `\docat` makron argumentissa, kuten `\docat{$90}`?

```
\begin{document}
\def\docat #1{\catcode`\$=11 #1}
I paid \docat{$90} for that book.
\end{document}
```

Kuten yllä selitettiin, kun TeX käy läpi syötettäsi ja tunnistaa makrokomennon — silloin kun TeX on aikomassa suorittaa sen — TeX tarkistaa ensin, ottaako makro parametreja. Jos ottaa, TeX:n on sitten luettava syöttötiedostoa lisää tunnistaakseen varsinaiset *argumentit* käyttäjän tämän nimenomaisen makrokutsun yhteydessä antamat: TeXin on tehtävä tämä **ennen kuin** ennen kuin se voi kutsua varsinaisen makrokoodin. Selvää on, että TeXin täytyy määrittää data, jonka käyttäjä haluaa antaa makrolle.

Tunnistaakseen syötteessä olevat argumentit (käyttäjän makrokutsun), TeX:tä ohjaa kyseisen makron sisäisesti tallennettu määritelmä: tarkemmin sanottuna `<parametriteksti>` tallennetun makromääritelmän osa (tokenilista) — joka toimii eräänlaisena “tokenimallina”. Tämän “tokenimallin” avulla TeX:n on pääteltävä, mitkä *tokenit* käyttäjän makrokutsussa ovat vain *erottimet* (käytännössä “välimerkkejä”) ja mitkä *tokenit* muodostavat osan *argumentista*. Kun TeX kohtaa **sovitusparametri** tokenin tallennetussa makromääritelmässä `<parametriteksti>` osassa (“tokenimallissa”), että sen täytyy alkaa muodostaa *tokenilistaa* kyseiselle argumentille.

Heti kun TeX tunnistaa tarpeen määrittää käyttäjän argumentti, se käy syötteen läpi muodostaakseen tokeneita ja tarkistaa ne hyvin huolellisesti, tokeni tokenilta, tallennettua makromääritelmää vasten. TeX jatkaa tokenien keräämistä argumenttiin, kunnes se havaitsee tokenin, joka on oikeasti erotin, tai jos se havaitsee **lopetussovitus** tokenin: kummassakin tapauksessa TeX tietää, että on aika lopettaa kyseisen argumentin osaksi kuuluvien tokenien etsiminen.

### Miksi \docat-makro epäonnistui

Kuten todettiin, *ennen kuin* Jotta TeX voi todella kutsua makron, sen on tunnistettava ja valmisteltava kaikki argumentit, joita käytetään kyseisen makron kanssa. Argumenttien tunnistamiseksi, valmiina syötettäväksi makroon, TeX:n täytyy kuitenkin muodostaa kukin argumentti *tokenilistaa*tokenilistaksi `\docat`epäonnistumiseen.

Esimerkissämme annoimme `\docat` sille argumentin `$90` mutta tuo argumentti *muunnetaan ensin tokenilistaksi* kun TeX käy läpi makrokutsua — argumentti muunnetaan tokeneiksi *ennen kuin* ennen kuin makroa todella kutsutaan. Tässä argumentille `$90`TeX muodostaa kolme merkkitokenia: yhden tokenin kutakin `$`, `9` ja `0`.

Seuraava kuva näyttää argumentille luodun tokenilistan `$90`ennen kuin se syötetään `\docat` makrolle:

![TeX-tokenilista, joka on muodostettu makroargumentille](/files/4188322551927c9b2023a26ed3137dfdeab36afb)

Yllä olevasta kuvasta näemme selvästi, että argumentin tokenilista sisältää `$` merkkinä tokenina kategoriakoodilla 3.

Kuten näimme osissa 1–3, merkkitokenit luodaan käyttäen kategoriakoodeja *jotka ovat voimassa sillä hetkellä, kun merkki luetaan sisään*—eli silloin, kun argumentin tokenilista luodaan (muunnetaan tokeneiksi). Kun argumentteja tokenisoidaan, `\docat` makroa ei ole vielä suoritettu, joten makrokutsussa tekemämme kategoriakoodin muutos (``\catcode`\$=11``) *ei* ei vaikuta argumentin tokenien luomiseen käytettäviin kategoriakoodeihin.

Kun TeX on muodostanut tokenilistan, joka edustaa `$90`, nuo kolme merkkitokenia syötetään varsinaiseen makroon `<korvausteksti>`. Tämä kuitenkin johtaa `$` siihen, että se syötetään *merkkitokeniksi* kategoriakoodilla 3 luotuna: “math on”, ja olemme nähneet, että kun merkkitokeni on muodostettu, siihen liitetty kategoriakoodi on pysyvä.  `$` on *sisällä* makroon syötetty *merkkinä*, vaan *merkkitokeniksi* pohjautuvana `$` sillä on kategoriakoodi 3.

### \docat:n suoritus: makrolaajennus

TeX viittaa makron “suorittamiseen” nimellä *makrolaajennus*; termi, joka tämän kirjoittajan mielestä on hieman hämmentävä, mutta se on vakiintunut terminologia, joten jatkamme sen käyttöä.

#### Makrolaajennuksen todellinen merkitys

Kun TeX havaitsee `\docat` komennon käyttäjän syötteessä, se käy argumentit läpi ja muodostaa tokenilistan sen argumentille(`$90`). Makron suorittamiseksi (laajentamiseksi) TeX kääntää katseensa pois käyttäjän syöttötiedostosta ja alkaa lukea tokeneita, jotka sisältyvät `\docat`’n `<korvausteksti>` TeXin muistiin tallennettuun tokenilistaan.

Kun TeX käsittelee `\docat`määritelmää, se näkee ja suorittaa sitten tokenisarjan, jota alun perin käytettiin makron määrittämiseen (`**catcode**`, ``**`**``, `**\$**`, `**=**`, `**1**`, `**1**`, `**#1**`).

Seuraava kuva näyttää `\docat` makron laajentamisen prosessin: TeX lakkaa saamasta tokeneita syöttötiedostosta ja alkaa lukea tokeneita `<korvausteksti>` osasta `\docat` makromääritelmästä, joka on tallennettu muistiin. TeX jatkaa näiden valmiiksi valmisteltujen tokenien suorittamista, kunnes se näkee **ulostuloparametri** tokenin, joka ohjeistaa TeXiä lukemaan (“injektoimaan”) ja “suorittamaan” argumentin tokenit tässä kohdassa. Esimerkissämme kyseessä on kolme merkkitokenia, jotka edustavat `$90` ja tämä johtaa virheeseen, koska valmiiksi valmisteltu merkkitoken `$` sillä on kategoriakoodi 3. Koska käsittelemme merkkitokeneita, emme merkkejä, `$` ei aiempi kategoriakoodin muutos, jonka tokeneissa ``\catcode`\$=11``.

![Näytetään \docat-makron laajentamisprosessi](/files/c7795a3301dc91b5106b4d6da5f5043e943cdf60)

Kun TeX on käsitellyt tokeneita, jotka edustavat ``\catcode`\$=11``, kategoriakoodin muutos `$` on nyt voimassa. Tämän jälkeen TeX kohtaa “erikoistokenin”, jonka nimi on **ulostuloparametri** joka kertoo TeXille, että sen on **lisäävät** argumentin tokenilista. Kuitenkin tuo tokenilista on kolme merkkitokenia *tokenit*, joista ensimmäinen on tokeni `$` jolle on annettu kategoriakoodi 3 (“math on”): makron sisäinen aiempi kategoriakoodin muutos ei voi vaikuttaa tähän merkkitokeniin, joten TeX tulkitsee tokenin signaaliksi aloittaa matematiikan käsittelyn, mikä aiheuttaa makron epäonnistumisen.

### Voiko \docat-makron korjata?

Yllä käydyistä keskusteluista on selvää, että kaikki makroargumenteissa esiintyvät merkit tokenisoidaan käyttäen niitä kategoriakoodeja, jotka ovat voimassa tokenisoinnin tapahtumahetkellä — mikä esimerkissämme on *aina* ennen kuin `<korvausteksti>` sisällä `\docat` makro todella suoritetaan. Miten siis voimme varmistaa, että makron argumenttien kategoriakoodit muuttuvat?

Yksi tapa on muokata `\docat` sellaiseksi parametrittomaksi makroksi, joka vain tekee kategoriakoodimuutoksen — sillä ei ole yhtään argumenttia tokenisoitavana. Sitten käytämme toista makroa, `\getarg`joka ottaa yhden parametrin, ja järjestämme niin, että sen argumentti tokenisoidaan silloin, kun oikea kategoriakoodi `$` on käytössä.

```
\begin{document}
\def\docat{\catcode`\$=11 \getarg} % Ei parametreja, kutsuu toista makroa \getarg
\def\getarg#1{#1} %1 parametri, jonka argumentti tokenisoidaan
Nyt voit suorittaa sen näin, ja se toimii:

I paid \docat{$90} for that book.
\end{document}
```

Kun käytämme uutta versiota `\docat` (näin `\docat{$90}`) se *näyttää* siltä kuin `$90` olisi yhä käytössä argumenttina `\docat` makrolle. Kuitenkin, kuten yllä käsiteltiin, kun TeX havaitsee `\docat` syötteessä se tarkistaa, onko sillä argumentteja: nyt ei ole, joten TeX ryhtyy suorittamaan (laajentamaan) sitä.  `\docat` on tokenien sarja `**catcode**`, ``**`**``, `**\$**`, `**=**`, `**1**`, `**1**`, `**väli**`, `**getarg**` ja tämä tapahtuu *ennen kuin* kun TeX alkaa lukea (tokenisoida) syöttötiedostossa olevia seuraavia merkkejä — eli ryhmää `{$90}`. Muista, että kun TeX laajentaa makron, se saa seuraavan syötteensä lukemalla tokenit, jotka sisältyvät kyseisen makromääritelmän tokenilistaan; eli sen `<korvausteksti>` muistiin tallennettuun osaan.

TeX käsittelee ja suorittaa `\docat` sekä havaitsee *tokenin* **`getarg`**, tunnistaen sen tokeniksi, joka edustaa komentoa, joka ottaa parametreja. Tässä vaiheessa TeX käy syöttötiedostoa läpi löytääkseen **`getarg`**&#x61;rgumentin: merkit: `{$90}`. Kuten tavallista, ne tokenisoidaan, mutta koska TeX on lukenut ja käsitellyt `\docat`, merkit `$90` tokenisoidaan silloin, kun `$` kategoriakoodi on muutettu arvoon 11. Määritelmä (`<korvausteksti>`) `\getarg` on yksinkertaisesti `#1` mikä tarkoittaa annetun argumentin ladelointia, ja niin myös tapahtuu, jolloin tuloksena on `$` luodaan merkki, jonka kategoriakoodi on 11, ja se ladotaan turvallisesti.

## Lopuksi: tarina solmuina

Tapahtumaketju, joka syntyy kirjoitettaessa uudelleen `\docat` käyttämään makroa `\getarg` sisältyy seuraavaan kommentoituun solmulistakaavioon, joka näyttää makron `\docat`. Lukijat, jotka haluavat tutkia tätä kaaviota tarkasti, voivat ladata kuvan [PDF](https://assets.ctfassets.net/nrgyaltdicpt/7MOBdavza4WxAEQGISEEht/cabe5097d9063a6415bc553cd38237e6/newdocatexpansion.pdf) tai [SVG](https://images.ctfassets.net/nrgyaltdicpt/2FIqqVRXjakdAzTpZsV0m9/10ccc1353741d42d3df18f1692d8aa84/newdocatexpansion--plain.svg) tiedostona offline-käyttöä varten.

![Näytetään muokatun \docat-makron ja \getarg-makron laajentamisprosessi](/files/dd64d1ad2e7ba3ed777e7b6a8756f9e54dc26c61)

[Osa 1](/latex/fi/lisaa-aiheita/19-how-tex-macros-actually-work-part-1.md) [Osa 2](/latex/fi/lisaa-aiheita/20-how-tex-macros-actually-work-part-2.md) [Osa 3](/latex/fi/lisaa-aiheita/21-how-tex-macros-actually-work-part-3.md) [Osa 4](/latex/fi/lisaa-aiheita/22-how-tex-macros-actually-work-part-4.md) [Osa 5](/latex/fi/lisaa-aiheita/23-how-tex-macros-actually-work-part-5.md) [Osa 6](/latex/fi/lisaa-aiheita/24-how-tex-macros-actually-work-part-6.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/lisaa-aiheita/24-how-tex-macros-actually-work-part-6.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.
