> 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/pl/artykuly-szczegolowe/17-how-does-expandafter-work-a-detailed-macro-case-study.md).

# Jak działa \expandafter: szczegółowe studium przypadku makra

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

## Studium przypadku: \expandafter przykład z The $$\varepsilon\mathrm{\text{-}{\TeX}}$$ Podręcznik

Ta $$\varepsilon\mathrm{\text{-}{\TeX}}$$ silnik składu tekstu został wywiedziony z oprogramowania TeX Knutha i pierwotnie miał służyć jako „tymczasowy” krok w kierunku opracowania [Nowego systemu składu tekstu](https://en.wikipedia.org/wiki/New_Typesetting_System) (NTS), napisanego w języku programowania Java. $$\varepsilon\mathrm{\text{-}{\TeX}}$$ został po raz pierwszy opracowany pod koniec lat 90., aby dodać zestaw nowych poleceń pierwotnych, które zapewniają dodatkową funkcjonalność niedostępną w oryginalnym programie Knutha. Chociaż $$\varepsilon\mathrm{\text{-}{\TeX}}$$ otrzymywał okresowe aktualizacje od chwili swojego pierwszego wydania, dziś nie jest szeroko używany jako samodzielny silnik składu tekstu, choć jego innowacje zostały wchłonięte przez późniejsze generacje TeX-a: pdfTeX, XeTeX i LuaTeX.

Ta [$$\varepsilon\mathrm{\text{-}{\TeX}}$$ manual](http://mirror.ox.ac.uk/sites/ctan.org/systems/doc/etex/etex_man.pdf) zawiera pouczający przykład makra, które sprytnie wykorzystuje `\expandafter`:

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

`\foo` implementuje mechanizm pętli, tak że `\foo{7}{13}` daje w wyniku `7, 8, 9, 10, 11, 12, 13`; jednakże, `\foo` nie używa żadnych *przypisań do zmiennych* w celu sterowania procesem pętli — co czyni je interesującym makrem do zbadania nieco dokładniej.

### Trochę tła: wyrażenia i przypisania

Ważnym elementem `\foo`kodu jest użycie polecenia `\numexpr`, polecenia z zestawu czterech powiązanych prymitywów po raz pierwszy wprowadzonych przez $$\varepsilon\mathrm{\text{-}{\TeX}}$$: `\numexpr`, `\dimexpr`, `\glueexpr` i `\muexpr`. Ich celem jest konstruowanie tzw. *wyrażeń* które pozwalają na obliczanie/manipulowanie wartościami TeX typu number, dimen, glue lub muglue (odpowiednio). Jak omówiono na stronach 8–9 The $$\varepsilon\mathrm{\text{-}{\TeX}}$$ Podręcznika, ważną cechą *wyrażeń* jest to, że ich ocena (obliczenie) nie wymaga od TeX-a wykonywania żadnych *przypisań*.

W terminologii programistycznej przypisanie to proces ustawiania (przypisywania) zmiennej tak, aby miała określoną wartość; na przykład przypisanie `\count` rejestru `99` tak, aby zawierał wartość `12345` za pomocą `\count99=12345`. Podczas przetwarzania TeX-a zachodzi wiele innych rodzajów przypisań — na przykład przypisywanie rejestrom tokenów zawierania ciągu tokenów, przypisywanie rejestrom pudełek zawartości pudełek itd.

Aby wykonać przypisanie, takie jak `\count99=12345`, TeX musi uruchomić (wykonać) wewnętrzny kod, który implementuje zachowanie `\count` lub dowolnego innego prymitywu wykonującego jakiś rodzaj przypisania. Jednak zdarzają się chwile, gdy TeX wykonuje wyłącznie *rozwijanie* i w takich momentach takie przypisania nie są wykonywane —*w tym momencie przetwarzania TeX-a*. Przykłady takiej sytuacji obejmują następujące polecenia:

* `\edef\command {*token list*}` polecenie definicji makra „rozwinięta definicja”, które rozwija tokeny w *liście tokenów* i zapisuje wynik jako definicję `\command`.
* `\write *number* {*token list*}` rozwija tokeny w `*token list*` i zapisuje je do pliku reprezentowanego przez `*number*`.
* `\directlua {*token list*}` to polecenie prymitywne LuaTeX służące do przekazywania kodu Lua do wbudowanego interpretera Lua. Wszystkie tokeny w `*token list*` są całkowicie rozwijane przed przekazaniem ich do interpretera Lua do wykonania.

#### Krótki przykład \edef

Jeśli zapiszemy następujące podstawowe makra:

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

`\edef` zostanie rozwinięte `\mycount` w jego składowe tokeny, ale nie idzie dalej: żadne z poleceń zawartych w definicji `\mymacro` nie zostanie wykonane: tzn. przypisanie `12345` na `\count99` *nie zachodzi w tym momencie*; dopiero gdy wywołamy `\mymacro` to przypisanie nastąpi, gdy TeX wykona kod przetwarzający `\count` prymityw. Gdy TeX wykonuje *czynności wyłącznie rozwijania* wszelkie przypisania zostaną wykonane później w przetwarzaniu TeX-a, a nie podczas samego procesu rozwijania.

#### Dlaczego przypisania są tutaj istotne?

Podczas pisania kodu wykonującego pętlę — w dowolnym języku programowania — powszechną praktyką jest mieć zmienną wyznaczoną do roli „licznika pętli”: używaną do kontrolowania liczby wykonań pętli. Pętlę zazwyczaj kontroluje się przez sprawdzanie, czy ta wyznaczona zmienna licznika pętli osiągnęła określoną wartość — zmienna ta jest zwiększana (lub zmniejszana) przy każdej iteracji pętli. Jednak modyfikacja zmiennej licznika pętli oznacza przypisanie jej nowej wartości, co w TeX-ie zwykle wymaga polecenia prymitywnego `\advance` do zwiększenia (lub zmniejszenia) wartości przechowywanej w `\count` rejestrze. Jak widzieliśmy, podczas czystego procesu rozwijania TeX-a takie przypisania (w tym zwiększanie zmiennych) nie mogą zachodzić: makro `\foo` sprytnie omija to ograniczenie.

### Wróćmy do wyjaśniania \foo

Makro `\foo` jest w stanie kontrolować proces pętli *bez* bez konieczności przypisywania wartości jakimkolwiek zmiennym: kontroluje, jak często pętla jest wykonywana, używając danych powstałych w wyniku rozwijania: wartości danych przechowywanych w tymczasowych listach tokenów. Korzystając z naszej wiedzy o użyciu (tworzeniu) przez TeX tymczasowych list tokenów, możemy przyjrzeć się bliżej, by zobaczyć dokładnie, jak `\foo` osiąga swoje rezultaty.

**Pamiętaj**: Analizujemy wykonanie makra po tym, jak oryginalny tekst jego definicji — zawarty w fizycznym `.tex` pliku — został przeskanowany (wczytany przez TeX) i przekształcony w listę tokenów reprezentującą definicję makra. W istocie śledzimy przetwarzanie przez TeX tych zapisanych *tokeny* podczas gdy odczytuje i przetwarza tokeny w definicji makra znajdującej się gdzieś w pamięci TeX-a. Wszelkie znaki spacji pierwotnie obecne w kodzie TeX definicji makra (tekst wewnątrz `.tex` pliku) zostały wchłonięte podczas skanowania tego tekstu przez TeX w poszukiwaniu poleceń (spacje jako terminatory) albo zostały przekształcone w tokeny, takie jak znak spacji po przecinku (`,`) w `\ifnum#1<#2,` który powstał w wyniku przekształcenia znaku końca wiersza (`\\r`) w spację.

Ponieważ kod TeX w `\foo` używa wielu `\expandafter` poleceń, ułatwimy nasze wyjaśnienie, dodając indeksy dolne do każdego `\expandafter`, wskazując, do którego się odnosimy. Dodatkowo rozszerzymy zapis dla tokenów przetwarzanych przez `\expandafter` na $$\mathrm{T^i\_1}$$ i $$\mathrm{T^i\_2}$$, reprezentując tokeny $$\mathrm{T\_1}$$ i $$\mathrm{T\_2}$$ dla `\expandafter<sub>i</sub>`: `\expandafter<sub>i</sub>` $$\mathrm{T^i\_1T^i\_2}$$

Oto opatrzony komentarzem kod makra:

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

`\foo` zaczyna się od `\number#1` które używa rozwijalnego polecenia `\number` do przekształcenia wartości pierwszego argumentu w jej postać złożoną. Polecenie `\number` polecenie działa, generując tymczasową listę tokenów zawierającą tokeny znakowe reprezentujące pojedyncze cyfry zawarte w wartości liczbowej, na której `\number` pracuje. Ta lista tokenów staje się następnym źródłem wejścia TeX-a. Tutaj ta lista tokenów jest odczytywana, a tokeny są wyprowadzane, aby złożyć wartość `#1`.

Następnie makro wykonuje test `\ifnum#1<#2` aby sprawdzić, czy argument dla `#1` jest mniejszy niż argument przekazany dla `#2`. Jeśli tak, token przecinka (`,`) jest wyprowadzany (złożony), a po nim pojawia się pewna spacja wynikająca z tokena wygenerowanego z znaku łamania wiersza po przecinku (`,`). Ten znak spacji został najpierw wygenerowany, gdy TeX odczytał ten wiersz z `.tex` pliku.

Makro kontynuuje, przetwarzając ten następny fragment kodu, który stanowi rdzeń jego działania:

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

W istocie ten kod generuje serię tymczasowych list tokenów, które skutkują wielokrotnymi wywołaniami `\foo` makra, kończąc, gdy test if `\ifnum#1<#2` nie jest już spełniony. Ale *jak* czy pętla jest kontrolowana, skoro nie zachodzą żadne przypisania: gdzie jest „licznik pętli”?

Zacznijmy od przyjrzenia się kodowi `\expandafter<sub>1</sub>\foo\expandafter<sub>2</sub>`. Zauważmy, że będziemy używać zapisu z indeksami dolnymi `<sub>token</sub>` (lub `<sub>(token)</sub>`) aby przypomnieć sobie, że tutaj TeX odczytuje/przetwarza numeryczne (całkowite) wartości tokenów.

Tutaj jako dane wejściowe dla `\expandafter<sub>1</sub>`:

* $$\mathrm{T^1\_1} =$$`\foo<sub>token</sub>` który jest wczytywany i przechowywany do późniejszego *ponownego wstawienia* z powrotem do wejścia
* $$\mathrm{T^1\_2} =$$`\expandafter<sub>2 (token)</sub>` który jest rozwijany

Dla `\expandafter<sub>2</sub>` mamy:

* $$\mathrm{T^2\_1} =$$`{<sub>token</sub>` który zostaje zachowany na później *ponownego wstawienia* z powrotem do wejścia
* $$\mathrm{T^2\_2} =$$ `\number<sub>token</sub>` który jest rozwijany

**Uwaga:**`\number` jest rozwijalnym poleceniem, którego celem jest „konwersja na tokeny”: czyli przekształcenie wielkości liczbowej w serię tokenów znakowych reprezentujących tę wielkość. Gdy `\number` zostaje rozwinięte, pierwszą rzeczą, jaką robi TeX, jest skanowanie wejścia w poszukiwaniu liczb całkowitych: proces ten uruchamia dalsze rozwijanie.

**Klucz do historii:** Tutaj, `\number` działa na *wyrażenie* `\numexpr#1+1` które oblicza wartość `#1+1`. Wynik tego obliczenia jest przetwarzany przez `\number` aby przekształcić go w tymczasową listę tokenów zawierającą tokeny znakowe reprezentujące wartość `#1 + 1`. Ta tymczasowa lista tokenów, wygenerowana przez `\number`, zostanie ostatecznie wczytana jako pierwszy argument kolejnego wywołania `\foo`. Zamiast zwiększać licznik pętli (za pomocą `\advance` i przypisania), użycie `\numexpr` tworzy nową wartość, ale bez konieczności przypisania. Dzięki temu mechanizmowi zmienna sterująca pętlą (`\foo`parametr `#1`) jest zwiększana, a iteracja pętli jest kontrolowana i kończy się: całkiem pomysłowe!

Następnie, `\expandafter<sub>3</sub>` jest przetwarzane, dając:

* $$\mathrm{T^3\_1} =$$`}<sub>token</sub>` który zostaje zachowany na później *ponownego wstawienia* z powrotem do wejścia
* $$\mathrm{T^3\_2} =$$`\expandafter<sub>4 (token)</sub>`, które jest rozwijane:

Dla `\expandafter<sub>4</sub>` mamy:

* $$\mathrm{T^4\_1} =$$`{<sub>token</sub>` który zostaje zachowany na później *ponownego wstawienia* z powrotem do wejścia
* $$\mathrm{T^4\_2} =$$`\number<sub>token</sub>` które jest rozwijane i przekształca `#2` w kolejną tymczasową listę tokenów.

Na koniec,`\expandafter<sub>5</sub>` jest rozwijane:

* $$\mathrm{T^5\_1} =$$`}<sub>token</sub>` który zostaje zachowany na później *ponownego wstawienia* z powrotem do wejścia
* $$\mathrm{T^5\_2} =$$`\fi<sub>token</sub>`, które jest rozwijalnym poleceniem.

  Rozwinięcie `\fi` w praktyce kończy `\ifnum` i w efekcie zamyka tę iterację makra. TeX teraz kończy ponowne wstawianie wszystkich tokenów tymczasowo zapisanych przez wielokrotne `\expandafter` polecenia: generuje to serię list tokenów jednoelementowych, powstałych z tokenów zapisanych przez każde `\expandafter`. Ponadto TeX utworzył także listy tokenów na podstawie działania `\number`.

### Składanie list tokenów

W istocie `\foo` makro generuje sekwencję list tokenów: można o `\foo` tym myśleć jako o „fabryce” list tokenów. Te listy tokenów są odczytywane przez TeX jako kolejne źródła wejścia. Sprytny element tkwi w jednym z wcześniejszych działań `\foo`:

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

dzięki któremu `\foo` sprawia, że wywołuje się ponownie, ale z innymi argumentami przechowywanymi w listach tokenów skonstruowanych przez `\number`. Aby te listy tokenów łącznie zachowywały się jak wywołanie makra, nawiasy klamrowe `{` i `}` zostały wszystkie zapisane i ponownie wstawione do wejścia (jako listy jedno-tokenowe) dzięki działaniom `\expandafter` poleceń.

![listy tokenów generowane przez makro \foo](/files/443b1d03ff29ff1e5760c8053b3ca9b1b204df40)

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