> 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/cs/clanky-do-hloubky/17-how-does-expandafter-work-a-detailed-macro-case-study.md).

# Jak funguje \expandafter: Podrobná případová studie makra

&#x20;[Část 1](/latex/cs/clanky-do-hloubky/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)   [Část 2](/latex/cs/clanky-do-hloubky/22-how-does-expandafter-work-the-meaning-of-expansion.md)   [Část 3](/latex/cs/clanky-do-hloubky/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md)   [Část 4](/latex/cs/clanky-do-hloubky/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md)   [Část 5](/latex/cs/clanky-do-hloubky/17-how-does-expandafter-work-a-detailed-macro-case-study.md)   [Část 6](/latex/cs/clanky-do-hloubky/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)&#x20;

## Případová studie: příklad s \expandafter z The $$\varepsilon\mathrm{\text{-}{\TeX}}$$ Příručka

Ta $$\varepsilon\mathrm{\text{-}{\TeX}}$$ sazební systém byl odvozen ze softwaru TeX od Knutha a původně měl sloužit jako „prozatímní“ krok směrem k vývoji [Nový sazební systém](https://en.wikipedia.org/wiki/New_Typesetting_System) (NTS), napsaný v programovacím jazyce Java. $$\varepsilon\mathrm{\text{-}{\TeX}}$$ byl poprvé vyvinut na konci 90. let, aby přidal sadu nových primitivních příkazů, které poskytují další funkcionalitu, jež nebyla dostupná v původním Knuthově programu. Ačkoli $$\varepsilon\mathrm{\text{-}{\TeX}}$$ od svého prvního vydání dostává pravidelné aktualizace, dnes se však jako samostatný sazební systém příliš nepoužívá, ačkoli jeho novinky byly převzaty do pozdějších generací TeXu: pdfTeX, XeTeX a LuaTeX.

Ta [$$\varepsilon\mathrm{\text{-}{\TeX}}$$ manual](http://mirror.ox.ac.uk/sites/ctan.org/systems/doc/etex/etex_man.pdf) obsahuje názorný příklad makra, které chytře využívá `\expandafter`:

```
    \def\foo#1#2{\number#1
    \ifnum#1<#2,
    \expandafter\foo
    \expandafter{\number\numexpr#1+1\expandafter}%
    \expandafter{\number#2\expandafter}%
    \fi}
```

`\foo` zavádí smyčkový mechanismus tak, že `\foo{7}{13}` vytvoří `7, 8, 9, 10, 11, 12, 13`; nicméně, `\foo` nepoužívá žádná *přiřazení proměnným* k řízení procesu smyčky — což z něj činí zajímavé makro k podrobnějšímu prozkoumání.

### Několik souvisejících poznámek: výrazy a přiřazení

Důležitým prvkem `\foo`jeho kódu je použití příkazu `\numexpr`, příkazu ze sady čtyř souvisejících primitiv, které byly poprvé představeny příkazem $$\varepsilon\mathrm{\text{-}{\TeX}}$$: `\numexpr`, `\dimexpr`, `\glueexpr` a `\muexpr`. Jejich účelem je sestavovat tzv. *výrazy* které umožňují výpočet/manipulaci s TeXovými hodnotami typu number, dimen, glue nebo muglue (v uvedeném pořadí). Jak je rozebráno na stranách 8–9 The $$\varepsilon\mathrm{\text{-}{\TeX}}$$ Příručka je důležitou vlastností *výrazy* je, že jejich vyhodnocení (výpočet) nevyžaduje, aby TeX prováděl jakákoli *přiřazení*.

V programátorských termínech je přiřazení proces, kdy se proměnné nastaví (přiřadí) určitá hodnota; například přiřazení `\count` registru `99` na hodnotu `12345` prostřednictvím `\count99=12345`. Během zpracování TeXu dochází k mnoha dalším typům přiřazení — například přiřazení tokenových registrů, aby obsahovaly posloupnost tokenů, přiřazení boxových registrů, aby obsahovaly obsah boxu, a tak dále.

Aby TeX provedl přiřazení, například `\count99=12345`, musí TeX aktivovat (spustit) interní kód, který implementuje chování `\count` nebo jakéhokoli jiného primitiva, které provádí nějaký druh přiřazení. Jsou však chvíle, kdy TeX provádí čistou *rozšiřování* a v takových chvílích se tato přiřazení neprovádějí —*v daném bodě zpracování TeXu*. Příklady této situace zahrnují následující příkazy:

* `\edef\command {*seznam tokenů*}` makropříkaz definice „rozšířené definice“, který rozšiřuje tokeny v *seznamu tokenů* a ukládá výsledky jako definici `\command`.
* `\write *číslo* {*seznam tokenů*}` rozšiřuje tokeny v `*seznamu tokenů*` a zapisuje je do souboru reprezentovaného `*number*`.
* `\directlua {*seznam tokenů*}` tento primitivní příkaz LuaTeXu se používá k předání kódu Lua vestavěnému interpretu Lua. Všechny tokeny v `*seznamu tokenů*` jsou před předáním interpretu Lua ke spuštění plně rozšířeny.

#### Rychlý příklad \edef

Pokud napíšeme následující základní makra:

```
     \def\mycount{\count99=12345}
     \edef\mymacro{\mycount}
```

`\edef` rozvine `\mycount` do jeho složkových tokenů, ale dál už nejde: žádný z příkazů obsažených v definici `\mymacro` bude proveden: tj. přiřazení `12345` na `\count99` *se v tomto okamžiku neprovede*; teprve když zavoláme `\mymacro` dojde k tomuto přiřazení, když TeX spouští kód pro zpracování `\count` primitiva. Když TeX provádí *činnosti pouze rozšiřování* jakákoli přiřazení budou provedena později při zpracování TeXu, nikoli během samotného procesu rozšiřování.

#### Proč jsou zde přiřazení zajímavá?

Při psaní kódu, který provádí smyčku — v jakémkoli programovacím jazyce — je běžnou praxí mít proměnnou určenou jako „čítač smyčky“: používá se k řízení počtu opakování smyčky. Smyčka je obvykle řízena testováním, zda tato určená proměnná čítače smyčky dosáhla určité hodnoty — tato proměnná se při každé iteraci smyčky zvyšuje (nebo snižuje). Úprava proměnné čítače smyčky však znamená přiřadit jí novou hodnotu, což v TeXu obvykle vyžaduje primitivní příkaz `\advance` ke zvýšení (nebo snížení) hodnoty uložené v `\count` registru. Jak jsme viděli, během čistého procesu rozšiřování TeXu se taková přiřazení (včetně zvyšování proměnných) nemohou provádět: makro `\foo` tu omezení chytře obchází.

### Zpět k vysvětlení \foo

Makro `\foo` dokáže řídit proces smyčky *bez* aniž by muselo přiřazovat hodnoty jakýmkoli proměnným: řídí, jak často se smyčka provádí, pomocí dat vznikajících při rozšiřování: hodnot dat uložených v dočasných seznamech tokenů. S využitím našich znalostí o používání (vytváření) dočasných seznamů tokenů v TeXu se můžeme podívat blíže a zjistit přesně, jak `\foo` dosahuje svých výsledků.

**Pamatujte**: Procházíme provádění makra poté, co původní text jeho definice — obsažený ve fyzickém `.tex` souboru — byl naskenován (načten TeXem) a převeden na seznam tokenů představující definici makra. V podstatě sledujeme zpracování těchto uložených *tokeny* zatímco čte a zpracovává tokeny v definici makra uložené někde v paměti TeXu. Jakékoli znaky mezery původně přítomné v kódu TeXu definice makra (text uvnitř `.tex` souboru) budou pohlceny při tom, jak TeX skenoval tento text pro příkazy (mezery jako ukončovače), nebo budou převedeny na tokeny, například znak mezery za čárkou (`,`) v `\ifnum#1<#2,` který vznikl převodem znaku konce řádku (`\r`) na mezeru.

Protože kód TeXu v `\foo` používá více `\expandafter` příkazů, usnadníme si vysvětlení přidáním indexů ke každému `\expandafter`, abychom označili, ke kterému z nich se vztahujeme. Kromě toho rozšíříme zápis pro tokeny zpracovávané `\expandafter` na $$\mathrm{T^i\_1}$$ a $$\mathrm{T^i\_2}$$, představující tokeny $$\mathrm{T\_1}$$ a $$\mathrm{T\_2}$$ pro `\expandafter<sub>i</sub>`: `\expandafter<sub>i</sub>` $$\mathrm{T^i\_1T^i\_2}$$

Zde je anotovaný kód makra:

```
    \def\foo#1#2{\number#1
    \ifnum#1<#2,
    \expandafter1\foo
    \expandafter2{\number\numexpr#1+1\expandafter3}%
    \expandafter4{\number#2\expandafter5}%
    \fi}
```

`\foo` začíná příkazem `\number#1` který používá rozšiřitelný příkaz `\number` k převodu hodnoty prvního argumentu do jeho vysázené podoby.  `\number` příkaz funguje tak, že vytváří dočasný seznam tokenů obsahující znakové tokeny, které představují jednotlivé číslice obsažené v číselné hodnotě, s níž `\number` pracuje. Tento seznam tokenů se stává dalším vstupním zdrojem TeXu. Zde je tento seznam tokenů přečten a tokeny jsou vypsány, aby vysázely hodnotu `#1`.

Dále makro provede test `\ifnum#1<#2` k ověření, zda argument pro `#1` je menší než argument předaný pro `#2`. Pokud ano, vypíše se token čárky`,`() (vysázen) a poté následuje určitá mezera vzniklá z tokenu, který byl vygenerován ze znaku zalomení řádku po čárce (`,`). Tento znak mezery byl nejprve vygenerován, když TeX četl tento řádek z `.tex` souboru.

Makro pokračuje zpracováním této další části kódu, která je jádrem jeho činnosti:

```
    \expandafter1\foo
    \expandafter2{\number\numexpr#1+1\expandafter3}%
    \expandafter4{\number#2\expandafter5}%
    \fi}
```

V podstatě tento kód generuje řadu dočasných seznamů tokenů, které vedou k mnohonásobnému volání `\foo` makra, končícímu, když je if-test `\ifnum#1<#2` už nepravdivý. Ale *jak* je smyčka řízena, protože se neprovádějí žádná přiřazení: kde je „čítač smyčky“?

Začněme pohledem na kód `\expandafter<sub>1</sub>\foo\expandafter<sub>2</sub>`. Všimněte si, že budeme používat zápis s indexy `<sub>token</sub>` (nebo `<sub>(token)</sub>`) abychom si připomněli, že zde TeX čte/zpracovává číselné (celé) hodnoty tokenů.

Zde máme následující tokeny jako vstup pro `\expandafter<sub>1</sub>`:

* $$\mathrm{T^1\_1} =$$`\foo<sub>token</sub>` který je načten a uložen pro pozdější *znovuvložení* zpět do vstupu
* $$\mathrm{T^1\_2} =$$`\expandafter<sub>2 (token)</sub>` který je rozšířen

Pro `\expandafter<sub>2</sub>` máme:

* $$\mathrm{T^2\_1} =$$`{<sub>token</sub>` který se uloží na později *znovuvložení* zpět do vstupu
* $$\mathrm{T^2\_2} =$$ `\number<sub>token</sub>` který je rozšířen

**Poznámka:**`\number` je rozšiřitelný příkaz, jehož účelem je „převést na tokeny“: tj. převést číselnou hodnotu na řadu znakových tokenů, které tuto hodnotu představují. Když `\number` je rozšířen, první věc, kterou TeX udělá, je prohledat vstup a hledat celá čísla: proces, který spouští další rozšiřování.

**Klíč k příběhu:** Zde `\number` působí na *výraz* `\numexpr#1+1` který vypočítává hodnotu `#1+1`. Výsledek tohoto výpočtu je zpracován pomocí `\number` k jeho převodu na dočasný seznam tokenů obsahující znakové tokeny představující hodnotu `#1 + 1`. Tento dočasný seznam tokenů, generovaný pomocí `\number`, bude nakonec načten jako první argument dalšího volání `\foo`. Místo zvyšování čítače smyčky (pomocí `\advance` a přiřazení) použití `\numexpr` vytváří novou hodnotu, aniž by bylo přiřazení nutné. Prostřednictvím tohoto mechanismu se proměnná řídící smyčku (`\foo`parametr `#1`) zvyšuje a iterace smyčky je řízena a ukončena: to je opravdu chytré!

Dále `\expandafter<sub>3</sub>` je zpracován, čímž vznikne:

* $$\mathrm{T^3\_1} =$$`}<sub>token</sub>` který se uloží na později *znovuvložení* zpět do vstupu
* $$\mathrm{T^3\_2} =$$`\expandafter<sub>4 (token)</sub>`, který je rozšířen:

Pro `\expandafter<sub>4</sub>` máme:

* $$\mathrm{T^4\_1} =$$`{<sub>token</sub>` který se uloží na později *znovuvložení* zpět do vstupu
* $$\mathrm{T^4\_2} =$$`\number<sub>token</sub>` který je rozšířen a převádí `#2` na další dočasný seznam tokenů.

Nakonec,`\expandafter<sub>5</sub>` je rozšířen:

* $$\mathrm{T^5\_1} =$$`}<sub>token</sub>` který se uloží na později *znovuvložení* zpět do vstupu
* $$\mathrm{T^5\_2} =$$`\fi<sub>token</sub>`, což je rozšiřitelný příkaz.

  Rozšíření `\fi` fakticky ukončuje `\ifnum` a ve skutečnosti uzavírá tuto iteraci makra. TeX nyní dokončí opětovné vložení všech tokenů dočasně uložených vícečetnými `\expandafter` příkazy: to generuje řadu jednoprvkových seznamů tokenů vzniklých z tokenů uložených každým `\expandafter`. Kromě toho TeX také vytvořil seznamy tokenů z prostřednictvím působení `\number`.

### Sestavování seznamů tokenů

V podstatě `\foo` makro generuje posloupnost seznamů tokenů: můžete si `\foo` představit jako „výrobní závod“ na seznamy tokenů. Tyto seznamy tokenů TeX čte, aby se staly dalším vstupním zdrojem. Chytrá část je obsažena v jednom z dřívějších kroků `\foo`:

```
    \expandafter1\foo\expandafter2
```

prostřednictvím něhož `\foo` zařídí, aby zavolalo samo sebe znovu, ale s různými argumenty, které jsou uloženy v seznamech tokenů vytvořených pomocí `\number`. Aby tyto seznamy tokenů společně fungovaly jako volání makra, složené závorky `{` a `}` byly všechny uloženy a znovu vloženy do vstupu (jako jednoprvkové seznamy) působením `\expandafter` příkazů.

![seznamy tokenů generované makrem \foo](/files/be82c883c59e4c8c971c3062e019240a95a7b9b9)

&#x20;[Část 1](/latex/cs/clanky-do-hloubky/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)   [Část 2](/latex/cs/clanky-do-hloubky/22-how-does-expandafter-work-the-meaning-of-expansion.md)   [Část 3](/latex/cs/clanky-do-hloubky/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md)   [Část 4](/latex/cs/clanky-do-hloubky/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md)   [Část 5](/latex/cs/clanky-do-hloubky/17-how-does-expandafter-work-a-detailed-macro-case-study.md)   [Část 6](/latex/cs/clanky-do-hloubky/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/cs/clanky-do-hloubky/17-how-does-expandafter-work-a-detailed-macro-case-study.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.
