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

# Jak naprawdę działają makra TeX-a: Część 6

[Część 1](/latex/pl/wiecej-tematow/19-how-tex-macros-actually-work-part-1.md) [Część 2](/latex/pl/wiecej-tematow/20-how-tex-macros-actually-work-part-2.md) [Część 3](/latex/pl/wiecej-tematow/21-how-tex-macros-actually-work-part-3.md) [Część 4](/latex/pl/wiecej-tematow/22-how-tex-macros-actually-work-part-4.md) [Część 5](/latex/pl/wiecej-tematow/23-how-tex-macros-actually-work-part-5.md) [Część 6](/latex/pl/wiecej-tematow/24-how-tex-macros-actually-work-part-6.md)

## Wprowadzenie i przegląd: Dotychczasowa historia

W ciągu poprzednich 5 części tej serii zobaczyliśmy:

* jak TeX odczytuje znaki w pliku wejściowym i używa kodów kategorii, aby rozpoznawać różne „klasy” znaków, a następnie konwertować je na tokeny znakowe i tokeny poleceń;
* że makro składa się w praktyce z czterech sekcji:

```
<prymityw makra TeX><nazwa makra><tekst parametrów>{<tekst podstawienia>}
```

gdzie:

* `<prymityw makra TeX>` = jedna z `\def`, `\edef`, `\gdef` lub `\xdef`;
* `<nazwa makra>`=nazwa Twojego makra, na przykład `\foo`;
* `<tekst parametrów>` może być „null” (nieobecny) albo może być ciągiem tokenów rozdzielających i tokenów parametrów makra;
* `<tekst zastępczy>` jest rzeczywistym ciałem Twojego makra: sekcją, która jest „wykonywana” (rozwijana), gdy wywołujesz makro.
* jak `<tekst parametrów>` sekcja może zawierać szeroki zakres tokenów i że TeX używa tej sekcji jako „szablonu tokenów”, aby dopasować wywołanie makra do jego pierwotnej definicji i ustalić argumenty użyte z makrem — oraz jak TeX oczekuje, że użycie makra będzie zgodne z jego pierwotną definicją;
* że wewnątrz TeX-a definicja makra jest przechowywana jako ciągły ciąg tokenów reprezentujących `<tekst parametrów>` i `<tekst zastępczy>` sekcje.

Gdy używasz polecenia makra, TeX najpierw sprawdzi, czy przyjmuje ono jakiekolwiek parametry. Jeśli tak, TeX musi następnie zidentyfikować rzeczywiste *argumenty* używane w Twoim wywołaniu makra. TeX musi przetestować Twoje wywołanie makra względem przechowywanej w pamięci definicji „szablonu tokenów”. Dokładniej, TeX używa swojej wewnętrznej (zapisanej) definicji `<tekst parametrów>` sekcji makra jako szablonu, przez który może wyodrębnić *tokeny* które są rzeczywistymi argumentami, i które *tokeny* służą jedynie jako ograniczniki.

## Znaczenie rozwijania makra

Jesteśmy teraz wreszcie gotowi przejść do najważniejszego tematu: jak TeX przetwarza argumenty makr i faktycznie wykonuje makro: proces, do którego TeX odnosi się jako *rozwijanie makra*.

### Ale najpierw krótki przykład: coś dziwnego?

Aby „ustawić scenę” do wyjaśnienia mechanizmu, dzięki któremu TeX przetwarza makra i ich argumenty, użyjemy krótkiego przykładu, aby wskazać kwestie, które musimy rozważyć.

#### Argumenty są najpierw konwertowane na tokeny

Poniższy przykład opiera się na przykładzie omówionym na stronach 114–5 [The Advanced TeXbook](https://www.amazon.co.uk/Advanced-Texbook-David-Salomon/dp/0387945563) napisanej przez Davida Salomona. Został wybrany, ponieważ bardzo dobrze ujmuje kluczowe idee w bardzo krótkim makrze TeX-a.

Podczas normalnej pracy TeX/LaTeX `$` znak ma kod kategorii 3 („math shift”), który przełącza TeX do/z trybu matematycznego w tekście (`$...$`) albo trybu matematycznego wyświetlanego (`$$...$$`) — oczywiście LaTeX używa `\(..\)` i `\[..\]` do tych samych celów.

Załóżmy, że chcemy makro, które zmienia kod kategorii znaku `$` na powiedzmy 11, tak aby można było złożyć go jak zwykły znak. Możemy użyć prymitywnego polecenia TeX-a `\catcode` i nasza pierwsza próba takiego makra, `\docat`, może wyglądać tak

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

Jednak gdy próbujemy go użyć, na przykład tak

```
\begin{document}
\def\docat #1{\catcode`\$=11 #1}
Zapłaciłem \docat{$90} za tę książkę.
\end{document}
```

oczekujemy, że TeX złoży `Zapłaciłem $90 za tę książkę.` ale kończy się to błędem:

```
! Wstawiono brakujący $.
<wstawiony tekst>
                $
<do ponownego odczytania>
                   \par
l.7
```

Z komunikatu błędu wygląda na to, że `$` użyty w argumencie naszego makra nadal uruchamia składanie matematyki przez TeX; jasno widać, że TeX *nie* zmienił kodu kategorii `$` użytego w argumencie naszego makra (`$90`). Pytanie brzmi *dlaczego* dlaczego TeX nie zmienił kodu kategorii `$` na 11 i nie złożył go jako zwykłego znaku? Krótka odpowiedź brzmi, że TeX najpierw konwertuje argumenty makra na tokeny **zanim** i przekazuje je do listy tokenów `<tekst zastępczy>`—ale mechanizmy leżące u podstaw przyjrzymy się znacznie dokładniej.

To, co musimy zapamiętać, to fakt, że nasze wyobrażenie o tym, że TeX używa tekstu/znaków, dotyczy tylko zawartości pliku, który TeX czyta: gdy tylko TeX odczyta jakiekolwiek znaki, wchodzimy do świata *tokeny*. Wywołania makr TeX-a działają na *tokeny*, a nie na rzeczywistej *zapisanej/tekstowej reprezentacji* poleceń TeX/LaTeX — stanie się to jaśniejsze, gdy przejdziemy przez przykład.

Początkowo możemy sądzić, że użycie `\docat` makra w `Zapłaciłem \docat{$90} za tę książkę.` jest tym samym co bezpośrednie zapisanie równoważnego kodu TeX-a (lub LaTeX-a) — na przykład poniższego, który *nie* działa:

```
\begin{document}
Zapłaciłem \catcode`\$=11 $90 za tę książkę.
\end{document}
```

![Jakiś kod TeX uruchomiony na Overleaf](/files/9c62085a8e3f9c71bd9ae3184515ca2b321a2d95)

Jednak, jak widzieliśmy powyżej, sposób, w jaki TeX przetwarza argumenty makra, daje wynik (`! Wstawiono brakujący $.`) dość inny niż zapisanie kodu TeX-a: teraz zbadamy *dlaczego* co się dzieje.

### Makra i argumenty jako listy tokenów

Aby w pełni zrozumieć zachowanie `\docat` makra oraz jego argumentu (`$90`), i dlaczego zawodzi, musimy ponownie wyobrazić sobie definicję `\docat` makra i wszelkich użytych argumentów (gdy wywoływane jest \docat) jako *listy tokenów*, a nie jako ciąg znaków.

Gdy TeX skanuje Twój tekst wejściowy, rozpoznałby `\docat` jako polecenie makra; potem sprawdza, czy przyjmuje ono jakieś parametry — jak TeX to robi, wyjaśniono w następnej sekcji dla czytelników zainteresowanych drobnymi szczegółami.

#### Dla tych, którzy lubią szczegóły...

Po wywołaniu makra TeX sprawdza, czy pierwszy token (w przechowywanej liście tokenów definicji makra) jest **tokenem końca dopasowania** jeśli tak, TeX może być pewien, że makro nie przyjmuje żadnych parametrów.

**Przykład**

Poniższe diagramy list węzłów porównują listy tokenów dla dwóch makr:

* `\def\foo A#1B{#1}`: to ma `<tekst parametrów>` o wartości `A#1B`, w konsekwencji token **tokenem końca dopasowania** jest **nie** pierwszym tokenem, więc TeX przystąpiłby do szukania parametrów;
* `\def\foo{X}`: to nie ma `<tekst parametrów>` sekcji, w konsekwencji token **tokenem końca dopasowania** jest pierwszym w liście tokenów i TeX wie, że nie ma szukać żadnych parametrów.

![Jak TeX sprawdza, czy makro przyjmuje parametry](/files/f19a17ca228c8ba600d4b62cdd720018f7b131e2)

## W stronę „wielkiego finału”: rozwijanie

Przypomnijmy sobie pytanie: dlaczego następujące makro nie działało; tzn. dlaczego TeX nie zmienia kodu kategorii żadnych `$` znaków użytych w argumencie `\docat` makra, takiego jak `\docat{$90}`?

```
\begin{document}
\def\docat #1{\catcode`\$=11 #1}
Zapłaciłem \docat{$90} za tę książkę.
\end{document}
```

Jak wyjaśniono powyżej, gdy TeX skanuje Twój tekst wejściowy i rozpoznaje polecenie makra — w momencie, gdy TeX ma je wykonać — TeX najpierw sprawdza, czy to makro przyjmuje jakieś parametry. Jeśli tak, TeX będzie musiał dalej skanować plik wejściowy, aby zidentyfikować rzeczywiste *argumenty* które użytkownik podał dla tego konkretnego wywołania makra: TeX musi to zrobić **zanim** zanim będzie mógł wywołać rzeczywisty kod makra. Oczywiście TeX musi ustalić dane, które użytkownik chce przekazać makru.

Aby zidentyfikować argumenty obecne w tekście wejściowym (wywołaniu makra przez użytkownika), TeX będzie kierował się wewnętrznie przechowywaną definicją tego makra: a dokładniej `<tekst parametrów>` sekcją zapisanej definicji makra (lista tokenów) — która dostarcza swego rodzaju „szablon tokenów”. Korzystając z tego „szablonu tokenów”, TeX musi ustalić, które *tokeny* w wywołaniu makra użytkownika są tylko *ograniczniki* (zasadniczo „interpunkcją”) i które *tokeny* stanowią część *argumentu*. To właśnie gdy TeX napotyka **token parametru dopasowania** w zapisanej definicji makra `<tekst parametrów>` sekcji („szablonie tokenów”), wie, że ma zacząć tworzyć *listę tokenów* dla tego konkretnego argumentu.

Gdy tylko TeX rozpozna potrzebę zidentyfikowania argumentu użytkownika, zacznie skanować tekst wejściowy, generować tokeny i bardzo dokładnie sprawdzać je token po tokenie względem zapisanej definicji makra. TeX kontynuuje zbieranie tokenów dla argumentu, aż wykryje token, który jest faktycznie separatorem, albo gdy wykryje **tokenem końca dopasowania** token końca dopasowania: w obu przypadkach TeX wie wtedy, że nadszedł czas, by przestać szukać tokenów stanowiących część tego argumentu.

### Dlaczego makro \docat nie zadziałało

Jak wspomniano, *zanim* Aby TeX mógł faktycznie wywołać makro, musi zidentyfikować i przygotować wszelkie argumenty, które mają być użyte z tym makrem. Jednak aby zidentyfikować argument(y) gotowe do przekazania do makra, TeX musi wygenerować każdy argument jako *listę tokenów*—i to jest powód `\docat`niepowodzenia.

W naszym przykładzie dostarczyliśmy `\docat` z argumentem `$90` ale ten argument jest najpierw *konwertowany na listę tokenów* gdy TeX skanuje wywołanie makra — argument jest konwertowany na tokeny *zanim* zanim makro zostanie faktycznie wywołane. Tutaj, dla argumentu `$90`, TeX wygeneruje trzy tokeny znakowe: jeden token dla każdego z `$`, `9` i `0`.

Poniższa grafika pokazuje listę tokenów wygenerowaną dla argumentu `$90`, przed przekazaniem jej do ciała `\docat` makra:

![Lista tokenów TeX wygenerowana dla argumentu makra](/files/52f298caa09b4383eea36e86629ac760f03683f5)

Na powyższej grafice wyraźnie widzimy, że lista tokenów argumentu zawiera `$` jako token znakowy oparty na kodzie kategorii 3.

Jak widzieliśmy w Częściach 1 do 3, tokeny znakowe są tworzone przy użyciu wartości kodów kategorii *obowiązujących w momencie odczytu znaku*—tj. w momencie tworzenia listy tokenów argumentu (zamieniania jej na tokeny). W chwili, gdy argumenty są tokenizowane, `\docat` makro nie zostało jeszcze wykonane, więc zmiana kodu kategorii, którą umieściliśmy w wywołaniu makra (``\catcode`\$=11``) *nie* nie wpływa na kody kategorii używane do generowania tokenów argumentu.

Gdy TeX wygeneruje listę tokenów reprezentującą argument `$90`, te trzy tokeny znakowe są przekazywane do rzeczywistego makra `<tekst zastępczy>`. Jednakże skutkuje to tym, że `$` jest przekazywany jako *tokenem znaku* utworzony przy użyciu kodu kategorii 3: „math on”, a widzieliśmy, że gdy token znakowy zostanie utworzony, przypisany kod kategorii jest trwały. Token `$` to *nie* przekazany do makra *nie jako znak*, lecz jako *tokenem znaku* oparty na `$` mającym kod kategorii 3.

### Uruchamianie \docat: rozwijanie makra

TeX odnosi się do procesu „wykonywania” makra jako *rozwijanie makra*; termin, który moim zdaniem jest nieco mylący, ale jest to przyjęta terminologia, więc będziemy nadal jej używać.

#### Prawdziwe znaczenie rozwijania makra

Po tym, jak TeX wykryje `\docat` polecenie w tekście wejściowym użytkownika, skanuje argumenty i generuje listę tokenów dla jego argumentu(`$90`). Aby wykonać (rozwinąć) makro, TeX odwraca wzrok od pliku wejściowego użytkownika i zaczyna czytać tokeny zawarte `\docat`jego `<tekst zastępczy>` w przechowywanej w pamięci liście tokenów.

Gdy TeX przetwarza `\docat`definicję, zobaczy on następnie i wykona serię tokenów użytych pierwotnie do zdefiniowania makra (`**catcode**`, ``**`**``, `**\$**`, `**=**`, `**1**`, `**1**`, `**#1**`).

Poniższa grafika pokazuje proces rozwijania `\docat` makra: TeX przestaje pobierać tokeny z pliku wejściowego i zaczyna czytać tokeny z `<tekst zastępczy>` sekcji `\docat` definicji makra przechowywanej w pamięci. TeX wykonuje te wcześniej przygotowane tokeny, aż zobaczy **token parametru wyjściowego** który instruuje TeX, by odczytał („wstrzyknął”) i „wykonał” tokeny argumentu w tym miejscu. W naszym przykładzie są to trzy tokeny znakowe reprezentujące `$90` i to powoduje błąd, ponieważ wcześniej przygotowany token znakowy dla `$` ma kod kategorii 3. Ponieważ mamy do czynienia z tokenami znakowymi, a nie znakami, `$` nie jest to zmienione przez wcześniejszą zmianę kodu kategorii spowodowaną przez tokeny w ``\catcode`\$=11``.

![Pokazanie procesu rozwijania makra \docat](/files/833eb2ed7b91eebd466927de0c2f307936d47e3e)

Po tym, jak TeX przetworzy tokeny reprezentujące ``\catcode`\$=11``, zmiana kodu kategorii dla `$` będzie teraz obowiązywać. TeX następnie napotyka „specjalny token” o nazwie **token parametru wyjściowego** który mówi TeX-owi, aby **wstawiają** listę tokenów dla argumentu. Jednak ta lista tokenów składa się z trzech tokenów znakowych, *tokeny*z których pierwszy jest tokenem `$` z przypisanym kodem kategorii 3 („math on”): wcześniejsza zmiana kodu kategorii w obrębie makra nie może wpłynąć na ten token znakowy, więc TeX traktuje go jako sygnał do rozpoczęcia przetwarzania matematycznego, co powoduje niepowodzenie makra.

### Czy makro \docat można naprawić?

Z powyższych omówień jasno wynika, że wszelkie znaki pojawiające się w argumentach makra są tokenizowane z użyciem kodów kategorii obowiązujących w momencie tokenizacji — co w naszym przykładzie jest *zawsze* przed `<tekst zastępczy>` środowisku `\docat` faktycznym wykonaniem makra. Jak więc możemy zapewnić, że kody kategorii argumentów makra zostaną zmienione?

Jednym ze sposobów jest zmodyfikowanie `\docat` tak, aby było makrem bezparametrowym, które tylko dokonuje zmiany kodu kategorii — nie ma żadnych argumentów do tokenizacji. Następnie używamy drugiego makra, `\getarg`, które przyjmuje jeden parametr, i tak je ustawiamy, aby jego argument został tokenizowany, gdy obowiązuje odpowiedni kod kategorii `$` jest aktywny.

```
\begin{document}
\def\docat{\catcode`\$=11 \getarg} % Bez parametrów, wywołuje drugie makro \getarg
\def\getarg#1{#1} %1 parametr, którego argument będzie tokenizowany
Teraz możesz uruchomić to tak i zadziała:

Zapłaciłem \docat{$90} za tę książkę.
\end{document}
```

Gdy używamy naszej nowej wersji `\docat` (takiej jak ta `\docat{$90}`) *wydaje się* jakby `$90` wciąż był używany jako argument dla `\docat` makra. Jednak, jak omówiono powyżej, gdy TeX wykrywa `\docat` w tekście wejściowym, sprawdza, czy ma jakiekolwiek argumenty: teraz ich nie ma, więc TeX przystępuje do wykonania (rozwinięcia) go. Rozwinięcie `\docat` to sekwencja tokenów `**catcode**`, ``**`**``, `**\$**`, `**=**`, `**1**`, `**1**`, `**space**`, `**getarg**` i odbywa się to *zanim* gdy TeX zaczyna czytać (tokenizować) następne znaki zawarte w pliku wejściowym — tj. grupę `{$90}`. Pamiętaj, że gdy TeX rozwija makro, kolejne wejście otrzymuje, czytając tokeny zawarte w liście tokenów definicji tego makra; tj. z jego `<tekst zastępczy>` sekcji przechowywanej w pamięci.

TeX przetworzy i wykona rozwinięcie `\docat` i wykryje *token* **`getarg`**, rozpoznając go jako token reprezentujący polecenie przyjmujące parametry. W tym momencie TeX przeskanuje plik wejściowy w poszukiwaniu **`getarg`**&#x61;rgumentu `{$90}`—znaki: `\docat`. Jak zwykle, są one tokenizowane, ale ponieważ TeX odczytał i przetworzył rozwinięcie `$90` , znaki `$` są tokenizowane, gdy kod kategorii`<tekst zastępczy>`został zmieniony na 11. Definicja ( `\getarg` ) `#1` to po prostu `$` co oznacza: złożyć podany argument, i właśnie to się dzieje, skutkując wygenerowaniem

## Zakończenie: historia w węzłach

Sekwencja zdarzeń wynikająca z przepisania `\docat` tak, aby użyć makra `\getarg` jest zawarta w poniższym opatrzonym komentarzami diagramie listy węzłów, który pokazuje proces rozwijania makra `\docat`. Czytelnicy, którzy chcą dokładnie przeanalizować ten diagram, mogą pobrać grafikę jako [plik PDF](https://assets.ctfassets.net/nrgyaltdicpt/7MOBdavza4WxAEQGISEEht/cabe5097d9063a6415bc553cd38237e6/newdocatexpansion.pdf) lub [SVG](https://images.ctfassets.net/nrgyaltdicpt/2FIqqVRXjakdAzTpZsV0m9/10ccc1353741d42d3df18f1692d8aa84/newdocatexpansion--plain.svg) do użytku offline.

![Pokazanie procesu rozwijania zmodyfikowanego makra \docat i makra \getarg](/files/5e08b884c5ddd6a985489e31712e1cc532973ccb)

[Część 1](/latex/pl/wiecej-tematow/19-how-tex-macros-actually-work-part-1.md) [Część 2](/latex/pl/wiecej-tematow/20-how-tex-macros-actually-work-part-2.md) [Część 3](/latex/pl/wiecej-tematow/21-how-tex-macros-actually-work-part-3.md) [Część 4](/latex/pl/wiecej-tematow/22-how-tex-macros-actually-work-part-4.md) [Część 5](/latex/pl/wiecej-tematow/23-how-tex-macros-actually-work-part-5.md) [Część 6](/latex/pl/wiecej-tematow/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/pl/wiecej-tematow/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.
