> 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/22-how-tex-macros-actually-work-part-4.md).

# Miten TeX-makrot oikeastaan toimivat: osa 4

[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

Osissa 1–3 sukelsimme syvälle joihinkin matalan tason taustatietoihin valmistautuaksemme ymmärtämään, miten TeX-makrot toimivat. Tässä artikkelissa ”nousumme pintaan” tarkastelemaan joitakin TeX-makrojen peruskäytännön periaatteita ennen uutta syväsukellusta osissa 5 ja 6. Koko tämän artikkelin ajan näytämme esimerkkimakroja, jotka on määritelty käyttäen TeX:n primitiivikomentoa `\def`: emme käytä ehkä tutumpaa LaTeX-komentoa `\newcommand`. Tähän on erittäin hyvä syy: tavoitteemme on ymmärtää TeX:n makrokäyttäytymisen taustalla olevat perusperiaatteet, mutta jotta voimme tehdä niin, meidän on käytettävä ytimen komentoja *sisäänrakennettuina* TeX-ohjelmistoon. LaTeX-komennot, kuten `\newcommand`, ovat itse makroja: komentoja, joilla on tietty ohjelmoitu käyttäytyminen ja jotka on lopulta rakennettu alempitason TeX-primitiivikomentojen kerroksista. Ymmärtääksemme TeX:n peruskäyttäytymistä paremmin meidän on käytettävä TeX-primitiivejä, ei LaTeX-makroja.

### Mihin olemme menossa?

Pohjimmiltaan pyrimme selittämään makrot token-luettelon erikoistuneena muotona: kun annat TeX:lle käskyn määritellä makron, se luo tokenien jonon (token-luettelon) ja tallentaa ne muistiinsa nimeen, jonka määrittelet. Osissa 5 ja 6 tarkastelemme makrojen token-luetteloita melko yksityiskohtaisesti, mutta jos haluaisit hypätä tästä artikkelista lukemaan taustatietoa, löydät sen kohdasta [Mikä on TeX-tokenlista?](/latex/fi/syvalliset-artikkelit/54-what-is-a-tex-token-list.md)

Makrojen token-luettelot ja niiden parametrit sisältävät muutamia lisävivahteita, jotka käymme läpi yksityiskohtaisesti — ja käytämme paljon esimerkkejä. Jotta TeX:n makrojen käsittelykäyttäytymistä ymmärtäisi paremmin, on oikeastaan yksi avainasia muistettavana: TeX ajattelee merkkeinä vain syötteen käsittelyn varhaisimmassa vaiheessa: siitä eteenpäin kaikki on tokeneita! Tässä artikkelissa ja tämän sarjan muissa artikkeleissa tutkimme tokenien roolia TeX-makroissa.

## Makron neljä osaa

### Muistutus: makroparametrit ja makroargumentit

Ennen kuin aloitamme, on hyvä palauttaa mieleen makron *parametrien* argumentit *argumentit*, koska käytämme molempia termejä koko tämän artikkelin ajan. Oletetaan, että määrittelet makron \foo

```
\def\foo#1#2{Tämä on #1, tämä on #2}
```

Rakenteet (tokenit) `#1`, `#2` (aina kohtaan `#9`) asti kutsutaan makron *parametrien*: ajattele niitä ”paikkamerkkeinä” varsinaiselle datalle, jota käytät, kun kutsut makroa:

```
\foo{alpha}{beta}
```

Tässä, `alpha` ja `beta` ovat *argumentit* tässä \foo:n kutsussa käytettyjä argumentteja: makron argumentit ovat ne todelliset arvot, jotka syötetään parametrien paikkamerkkeihin (`#1`, `#2`... `#9`), joita käytettiin, kun määrittelit makron.

### Makron määrittely: siinä on 4 elementtiä

Aloitamme siitä, mikä ehkä näyttää hieman muodolliselta makron määrittelyltä, mutta se tarjoaa hyödyllisen kehyksen myöhemmille keskusteluille.

Jokainen makron määrittely koostuu neljästä osasta:

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

jossa:

* `<TeX-makron primitiivi>`: yksi seuraavista `\def`, `\edef`, `\gdef` tai `\xdef`;
* `<makron nimi>`: makrokäskyllesi annettu nimi, kuten `\foo`;
* `<parametriteksti>`: tämä voi puuttua, mutta jos se on mukana, se on sarja *tokenit* jotka esiintyvät ennen `<korvausteksti>` makron osaa.  `<parametriteksti>` voi sisältää makroparametreja (`#1`, `#2`... `#9`) ja muita token-tyyppejä. Pohjimmiltaan, ja kuten näemme yksityiskohtaisesti,  `<parametriteksti>` tarjoaa eräänlaisen *token-mallin* jota TeX käyttää selvittääkseen, mitkä tokenit käyttäjä haluaa käyttää makron argumentteina: kun kutsut makroa, TeX syöttää *argumentista* tokenit makrosi `<korvausteksti>` (joka on myös token-luettelo);
* `{<korvausteksti>}`: tämä on makrosi varsinainen runko: se on tokenien sarja, johon *argumentit* argumentit ”injektoidaan” kun makroa käsitellään (laajennetaan). Argumentit syötetään niihin kohtiin, jotka makroparametrit osoittivat alkuperäisessä määrittelyssä.

**HUOM**: Koko keskustelun ajan oletamme, että `<makron nimi>` sen jälkeen seuraa kategoriakoodin 10 mukainen välilyöntimerkki toimimaan erottimena, joka päättää `<makron nimi>`makron määrittelyn. *emme ole* näyttäneet tuota välilyöntimerkkiä eksplisiittisesti tekstissämme/keskustelussamme, mutta oletamme sen olevan siellä. Tarkkaan ottaen meidän pitäisi esittää se jotakuinkin näin:

```
<TeX-makron primitiivi><makron nimi><välilyönti><parametriteksti>{<korvausteksti>}
```

Jätämme kuitenkin pois `<välilyönti>` -merkin eksplisiittisen sisällyttämisen ja oletamme sen läsnäolon implisiittisesti.

#### Huomioita {}-suluista

Olemme näyttäneet kahden aaltosulun käytön: `{` ja `}` jotka ympäröivät (rajaavat) makron `<korvausteksti>`. Kuitenkin `{` ja `}` käyttö on vain omaksuttu käytäntö, koska TeX itse asiassa odottaa, että makrosi teksti `<korvausteksti>` alkaa merkillä, jonka kategoriakoodi on 1 (“Aloita ryhmä”), ja päättyy merkkiin, jonka kategoriakoodi on 2 (“Lopeta ryhmä”). Käytännön mukaan nämä ovat `{` ja `}` merkit vastaavasti. Voit kuitenkin halutessasi antaa minkä tahansa merkkiparin hoitaa tämän. Esimerkiksi

```
\catcode`\(=1
\catcode`\)=2
```

Nyt voit määritellä ja käyttää makroja näin:

```
\def\foo #1(Hei, #1)
\foo(World!)
```

Ja voit yhä käyttää `{` ja `}` koska emme ole muuttaneet niiden kategorikoodeja — useilla merkeillä voi, ja on, olla sama kategorikoodi, joten voit jatkaa makrojen määrittelyä tavanomaisella tavalla:

```
\def\foo #1{Hei, #1}
\foo{World!}
```

### ja {}

Makron määrittelyn osista keskustelumme kannalta olennaisimpia ovat `<parametriteksti>` ja `{<korvausteksti>}`. Kun määrittelet makron,  `<parametriteksti>` on käytännössä tiukka token-malli, joka määrittää, miten makroa on tarkoitus käyttää. Kuten todettiin,  `<parametriteksti>` voi olla tyhjä esim., `\def\foo{Some text}` jossa mitään ei esiinny komentosi nimen (`\foo`) ja avaavan aaltosulun `{` välissä, joka tässä ilmaisee makron `<korvausteksti>`.

**Huomaa**: Jotkut lukijat saattavat tietää TeX:n ”hashquote”-mekanismista (`#{`) mutta emme puutu siihen tässä.

### ja makron erottimet

Tämä artikkeli ei ole suunniteltu täysin kattavaksi makrojen kirjoittamisen katsaukseksi, mutta on hyvä ottaa lyhyt kertaus muutamine esimerkkeineen, joka osoittaa, että `<parametriteksti>` voi muuttua monimutkaiseksi, koska TeX sallii `<parametriteksti>` sisältää:

* **makroparametreja**: (`#1`, `#2`,... `#9`) jotka toimivat ”paikkamerkkeinä” arvoille, jotka käyttäjä antaa, kun he suorittavat makron — makron *argumentit*;
* **erottimena toimivia tokeneita**: mielivaltaisia tokeneita, jotka on sijoitettu parametrien tokenien väliin/ympärille, ja joita käytetään määrittämään makroparametrien välinen raja. Voit ajatella näitä erottimia eräänlaisena ”välimerkityksenä”, joka tekee `<parametriteksti>` makron käytössä noudatettavaksi ”token-malliksi”. Erottimen tokenit eivät tule ladotuiksi.

Mitä tämä siis oikeastaan tarkoittaa — katsotaan joitakin esimerkkejä.  `<parametriteksti>` sijaitsee makron nimen ja vasemman aaltosulun `{` välissä makron määrittelyssä.

#### Erottimet: esimerkki 1

Oletetaan, että määrittelemme perusmakron `\foo` seuraavasti:

```
\def\foo ABC{hei, siellä}
```

* `<parametriteksti>` = `ABC`
* Parametrimerkkejä ei ole (`#1`, `#2`,... `#9`)
* Erottimet ovat *kolme merkkitokenia* `ABC` mutta tässä esimerkissä ne ovat jokseenkin tarpeettomia ja vain esimerkkinä.

Kolme merkkitokenia `ABC` käsitellään erottimina: ei sellaisena, joka ladotaan, vaan ”välimerkkinä”, jonka odotetaan olevan läsnä, kun makroa kutsutaan — kun käytät makroa `\foo` sinun on annettava samat erottimet, jotka olivat läsnä, kun se määriteltiin.

Jos kirjoitat `\foo ABC` tekstissäsi tämä ladotaan muodossa `hei, siellä`—merkkitokeneita `ABC` ei ladota, mutta TeX kyllä tarkasti varmisti, että ne olivat läsnä \foo:n kutsussa. `\foo`TeX etsii noita erottimia (”välimerkkejä”) ja poistaa (imee) ne, kuten seuraavasta Overleafin ruutukaappauksesta näet: `ABC` ei ladota:

![Overleaf suorittaa TeX-makroa](/files/80565018a988e2001ff5f9d65842dcf52bbb1e64)

Jos yrität käyttää `\foo` ilman `ABC` erottimia TeX valittaa `\foo:n käyttö ei vastaa sen määrittelyä.`:

![TeX-virheen näyttö Overleafissa](/files/527f414b62dc7f0990f097a51002882b97bd8997)

Yllä olevassa esimerkissä, havaittuaan `\foo` TeX odottaa näkevänsä nämä kolme merkkitokenia `ABC` mutta ei näe: se näkee merkkitokenin `w` ja huomaa välittömästi, että jokin on vialla.

#### Erottimet: esimerkki 2

Mielenkiintoinen, ja ehkä yllättäväkin, tosiasia on, että erottimet voivat olla mielivaltaisia komentotokeneita — mukaan lukien komennot, joita ei ole edes määritelty *edes määritelty*. Esimerkiksi voisimme määritellä `\foo` näin:

```
\def\foo A\bob B\anne{Hei \TeX{}}
```

* `<parametriteksti>` = `A\bob B\anne`
* Parametrimerkkejä ei ole (`#1`, `#2`,... `#9`)
* Erottimet ovat tokenit `A\bob B\anne` mutta jälleen tässä esimerkissä ne ovat tarpeettomia ja vain keskustelun vuoksi. Huomaa, että `\bob` ja `\anne` ovat kuvitteellisia komentoja, joita *ei ollut määritelty*—eikä niiden tarvitsekaan olla.

Kun kutsut makron, TeX tarkistaa (skannaa) `<parametriteksti>` että se on läsnä *makrokutsussasi* ja vertaa sitä token tokenilta muistissa tallennettuun ”token-malliin” *muistiin tallennettuun*—siihen, joka luotiin makron määrittelyhetkellä. TeX skannaa *käytetyt tokenit makrokutsussasi* ja muuntaa yksinkertaisesti kaikki sieltä löytämänsä komennot niiden numeeriseksi token-arvoksi: se ei yritä suorittaa näitä komentoja, joten sillä ei ole merkitystä, että `\bob` ja `\anne` eivät olleet koskaan määriteltyjä. TeX käyttää yksinkertaisesti muistiin tallennettua token-mallia ohjeena, jonka avulla se selvittää, mitkä tokenit makrokutsusi `<parametriteksti>` ovat todellisia argumentteja syötettäviksi `<korvausteksti>`.

Kuten seuraavasta Overleafin näytön katkelmasta näet, kumpikaan merkkitokeneista (`Yksi` ja `B`) sisällä `A\bob B\anne` ei ladottu, eivätkä määrittelemättömät komennot `\bob` ja `\anne` aiheuttaneet mitään ongelmia. Kaikki nämä tokenit *imeytyivät* TeX:n toimesta, kun se sovitti \foo:n käyttötapasi `\foo` määrittelyyn (token-malliin)  `\foo` (token-luettelo), joka oli tallennettu muistiin.

![Overleaf suorittaa TeX-makroa](/files/7214179b52cb78f37446d45cb3ccfef4f8a9edac)

#### Erottimet: esimerkki 3

Voit sijoittaa erilaisia erottimia (merkkitokeneita, komentotokeneita) makroparametrien väliin, kuten tässä esimerkissä:

```
\def\foo A\bob#1B\anne#2\jane#3bye!{Hei \TeX{}:ltä \#1=#1, \#2=#2 ja \#3=#3}
```

* `<parametriteksti>` = `A\bob#1B\anne#2\jane#3bye!`
* Makroparametrin tokeneita on 3: `#1`, `#2`, `#3`
* Tällä kertaa parametrit (`#1`, `#2`, `#3`) on rajattu tokenien yhdistelmällä:

  `A\bob#1B\anne#2\jane#3bye!`

Tässä olet käytännössä antanut TeX:lle mallin, jota se yrittää hyvin tarkasti sovittaa, ja jonka se odottaa täsmäävän, kun kutsut `\foo`: se käy makrokutsusi läpi *token tokenilta*ja odottaa täsmäävänsä (löytävänsä):

* kaksi tokenia `Yksi` ja `\bob` ennen kuin `#1`
* kaksi tokenia `B` ja `\anne` ennen kuin `#2`
* tokenin `\jane` ennen parametria `#3` ja *neljä merkkitokenia* `b`, `y`,`e` ja `!` jälkeen `#3`.

**Muista**Teksti: TeX ajattelee tokeneina, joten `bye!` on *neljä merkkitokenia*.

Tätä makroa voimme käyttää kahdella tavalla — voisimme laittaa kaikki monitokeniset argumentit aaltosulkeisiin ryhmän muodostamiseksi:

```
\foo A\bob{Tämä}B\anne{Tuo}\jane{Muu}bye!
```

Kuitenkaan sitä *ei tarvita* koska makromäärittelyssämme on erottimet, jotka tarjoavat token-mallin. TeX voi käyttää tuota mallia poimiakseen kunkin argumentin tokenit pelkästään erottimina toimivien tokenien joukosta. Voimme käyttää makroamme näin:

```
\foo A\bob TämäB\anne Tuo\jane Muubye!
```

ja TeX voi poimia argumentit tuottaakseen saman tuloksen kuin ryhmiä käyttämällä `{...}`:

![Overleaf suorittaa TeX-makroa erottimia käyttäen](/files/a431e4af75f2a1325211d64a8f03c6cfaaa2ac5a)

Huomaa, miten TeX pystyi täsmälleen havaitsemaan, mitkä tokenit vastasivat parametreja `#1` ja `#3`:

![Overleaf suorittaa TeX-makroa erottimia käyttäen](/files/73da2ceb5eedc9902cff1b26a5acc83fbc8ef5fa)

#### Erottimet: esimerkki 4 (kyse on tokeneista, ei merkeistä!)

Tässä on lyhyt esimerkki osoittamaan, että makrojen kanssa työskenneltäessä on tärkeää muistaa, että olemme todella tokenien maailmassa *tokenit* ja **sisällä** *merkkejä*…

Määritellään seuraava lyhyt makro, jossa A ja B ovat erottimina toimivia merkkejä ja molemmilla on kategoriakoodi 11. Tämä toimii ilman ongelmia:

```
\documentclass{article}
\begin{document}
\def\foo A#1B{Hei, #1}
\foo AGrahamB
\end{document}
```

ja ladottaa `Hei, Graham`.

Kuitenkin, jos muutat A:n tai B:n kategoriakoodin joksikin muuksi kuin 11, makrokutsu epäonnistuu. Oletetaan, että muutamme B:n kategoriakoodin arvoon 12 käyttäen ``\catcode`B=12`` ja yritämme kutsua makroa uudelleen, kuten ennen:

```
\documentclass{article}
\begin{document}
\def\foo A#1B{Hei, #1}
\foo AGrahamB % Tämä toimii
\catcode`\B=12\relax
\foo AGrahamB
\end{document}
```

Se epäonnistuu hieman hämmentävän virheen kanssa:

```
Loputon argumentti?
GrahamB \end {document}
! Tiedosto päättyi \foo:n käytön skannauksen aikana.
<inserted text>
                \par
<*> main.tex

Luulen, että olet unohtanut `}', mikä saa minut
lukemaan pidemmälle kuin halusit minun pysähtyvän.
Yritän toipua; mutta jos virhe on vakava,
sinun on nyt parempi kirjoittaa `E' tai `X' ja korjata tiedostosi.

! Hätäseis.
<*> main.tex

*** (tehtävä keskeytettiin, kelvollista \end-merkkiä ei löytynyt)
```

![Overleaf näyttää TeX-makron virheen](/files/2f755c1544aa974006ded6d805e4d297c31ccccc)

Valitettavasti TeX:n oletusehdotus ``Luulen, että olet unohtanut `}'`` on **virheellinen**, se ei johdu puuttuvasta aaltosulusta (`}`).

#### Mitä on tapahtunut?

TeX yrittää sovittaa `\foo` makroa *kutsun* määrittelyyn `\foo` makroa *joka sillä on tallennettuna muistissa. Kun kutsut makron, joka tarvitsee yhden tai useampia argumentteja, TeX:n täytyy tutkia (skannata) makron käyttöäsi selvittääkseen* antamasi argumentit tälle makrolle. Tässä TeX odottaa, että argumentti on puristettuna A:n (kategoriakoodi 11) ja B:n (kategoriakoodi 11) väliin. Muista: TeX ajattelee *argumentit* tokeneina *tokenit*, **sisällä** *merkkejä*.

A:n ja B:n token-arvot, $$\mathrm{T\_A}$$ ja $$\mathrm{T\_B}$$ vastaavasti, ovat:

$$\mathrm{T\_A = 256 \times 11 + 65 = 2881}$$ $$\mathrm{T\_B = 256 \times 11 + 66 =2882}$$

Kuitenkin, kun TeX jatkaa etsintäänsä, se näkee B:n *mutta* nyt sen kategoriakoodi on 12 ja tämä johtaa erilaiseen token-arvoon:

$$\mathrm{T'\_B= 256 \times 12 + 66 =3138}$$

Kohdassa `\foo` makromäärittelyssä B:n token-arvo (erottimena käytettynä) oli 2882, mutta TeX näkee nyt token-arvona 3138: se ajattelee tämän olevan vain toinen token, joka on tarkoitettu käytettäväksi *argumentista* annettuna `\foo`. TeX:n näkökulmasta argumentin viimeistä tokenia ei ole vielä löytynyt, joten se hakee vielä yhden tokenin etsiessään B:tä kategoriakoodilla 11. Silloin, ja siksi, makro epäonnistuu: yrittäessään löytää argumentin TeX “ylittää maaliviivan” ja alkaa lukea tokeneita, joita et tarkoittanut osaksi `\foo` makrokutsua. Se, mitä tapahtuu seuraavaksi, riippuu tokeneista, jotka TeX löytää B:n jälkeen — ne käynnistävät erilaisia `Loputon argumentti?` virheitä.

Esimerkissämme TeX ylittää maaliviivan ja imee tokensekvenssin `\end {document}` ja törmää nopeasti tiedoston loppuun, mistä seuraa virheilmoitus:

```
! Tiedosto päättyi \foo:n käytön skannauksen aikana
```

## Osa 5

Kuten yllä näimme, `<parametriteksti>` osuus makromme määrittelyssä voi vaihdella äärimmäisen yksinkertaisesta monimutkaiseen yhdistelmään makroparametreja, joiden väliin on sijoitettu merkkitokeneita ja komentotokeneita erottimina. TeX pystyy käsittelemään erilaisia kohdassa `<parametriteksti>` esiintyviä tokenien yhdistelmiä poimiakseen makrolle annetut argumentit — ja havaitsemaan, milloin yritämme käyttää makroa väärin. Miten se tekee tämän, on sarjan seuraavan artikkelin aihe.

[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/22-how-tex-macros-actually-work-part-4.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.
