> 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/uk/dokladni-statti/17-how-does-expandafter-work-a-detailed-macro-case-study.md).

# Як працює \expandafter: детальне дослідження макросу

&#x20;[Частина 1](/latex/uk/dokladni-statti/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)   [Частина 2](/latex/uk/dokladni-statti/22-how-does-expandafter-work-the-meaning-of-expansion.md)   [Частина 3](/latex/uk/dokladni-statti/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md)   [Частина 4](/latex/uk/dokladni-statti/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md)   [Частина 5](/latex/uk/dokladni-statti/17-how-does-expandafter-work-a-detailed-macro-case-study.md)   [Частина 6](/latex/uk/dokladni-statti/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)&#x20;

## Тематичне дослідження: \expandafter приклад з The $$\varepsilon\mathrm{\text{-}{\TeX}}$$ Посібник

Функція $$\varepsilon\mathrm{\text{-}{\TeX}}$$ верстальний механізм був похідним від програмного забезпечення TeX Кнута і спочатку замислювався як «тимчасовий» крок на шляху до розробки [Нової системи верстки](https://en.wikipedia.org/wiki/New_Typesetting_System) (NTS), написаної мовою програмування Java. $$\varepsilon\mathrm{\text{-}{\TeX}}$$ було вперше розроблено наприкінці 1990-х років, щоб додати набір нових примітивних команд, які забезпечують додаткову функціональність, недоступну в оригінальній програмі Кнута. Хоча $$\varepsilon\mathrm{\text{-}{\TeX}}$$ після початкового випуску отримувала періодичні оновлення, сьогодні вона не широко використовується як самостійний механізм верстки, хоча її нововведення були перейняті пізнішими поколіннями TeX: pdfTeX, XeTeX і LuaTeX.

Функція [$$\varepsilon\mathrm{\text{-}{\TeX}}$$ manual](http://mirror.ox.ac.uk/sites/ctan.org/systems/doc/etex/etex_man.pdf) містить показовий приклад макроса, який вдало використовує `\expandafter`:

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

`\foo` реалізує механізм циклу, так що `\foo{7}{13}` дає `7, 8, 9, 10, 11, 12, 13`; однак, `\foo` не використовує жодних *присвоєнь змінним* для керування процесом циклу — що робить його цікавим макросом для детальнішого розгляду.

### Коротка довідка: вирази та присвоєння

Важливим елементом `\foo`коду є використання команди `\numexpr`, команди з набору з чотирьох пов’язаних примітивів, уперше запроваджених $$\varepsilon\mathrm{\text{-}{\TeX}}$$: `\numexpr`, `\dimexpr`, `\glueexpr` та `\muexpr`. Їхня мета — будувати так звані *вирази* які дають змогу обчислювати/змінювати значення TeX типів number, dimen, glue або muglue (відповідно). Як обговорюється на сторінках 8–9 $$\varepsilon\mathrm{\text{-}{\TeX}}$$ Посібника, важливою характеристикою *вирази* є те, що їхнє обчислення (рахування) не вимагає від TeX виконувати жодних *присвоєнь*.

У термінах програмування присвоєння — це процес надання (призначення) змінній певного значення; наприклад, присвоєння `\count` реєстру `99` щоб містив значення `12345` через `\count99=12345`. Під час обробки TeX відбувається багато інших типів присвоєння — наприклад, присвоєння токен-реєстрам зберігати послідовність токенів, присвоєння бокс-реєстрам зберігати вміст боксів тощо.

Щоб виконати присвоєння, наприклад `\count99=12345`, TeX має активувати (виконати) внутрішній код, який реалізує поведінку `\count` або будь-якого іншого примітива, що виконує певний вид присвоєння. Однак бувають моменти, коли TeX виконує чисте *розширення* і в такі моменти такі присвоєння не виконуються —*на цій стадії обробки TeX*. Приклади такої ситуації включають такі команди:

* `\edef\command {*token list*}` команда макровизначення «розгорнуте визначення», яка розгортає токени в *список токенів* і зберігає результати як визначення `\command`.
* `\write *number* {*token list*}` розгортає токени в `*token list*` і записує їх у файл, представлений `*number*`.
* `\directlua {*token list*}` цей примітивний командний засіб LuaTeX використовується для передавання коду Lua вбудованому інтерпретатору Lua. Усі токени в `*token list*` повністю розгортаються перед передаванням інтерпретатору Lua для виконання.

#### Швидкий приклад \edef

Якщо ми запишемо такі базові макроси:

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

`\edef` розгорне `\mycount` у його складові токени, але далі не піде: жодна з команд, що містяться у визначенні `\mymacro` не буде виконана: тобто присвоєння `12345` на `\count99` *не відбувається на цьому етапі*; лише коли ми викличемо `\mymacro` це присвоєння відбудеться, коли TeX виконає код для обробки `\count` примітива. Коли TeX виконує *лише розгортання* будь-які присвоєння будуть виконані пізніше в процесі обробки TeX, а не під час самого процесу розгортання.

#### Чому присвоєння тут цікаві?

Під час написання коду для виконання циклу — будь-якою мовою програмування — зазвичай виділяють змінну, яка виступає як «лічильник циклу»: вона використовується для керування кількістю виконань циклу. Цикл зазвичай контролюють, перевіряючи, чи досягла ця змінна-лічильник певного значення — цю змінну збільшують (або зменшують) на кожній ітерації циклу. Однак зміна змінної-лічильника циклу означає присвоєння їй нового значення, що для TeX зазвичай вимагає примітивної команди `\advance` для збільшення (або зменшення) значення, що зберігається в `\count` реєстрі. Як ми вже бачили, під час чистого процесу розгортання TeX такі присвоєння (включно зі збільшенням змінних) не можуть відбуватися: макрос `\foo` винахідливо обходить це обмеження.

### Повернімося до пояснення \foo

Макрос `\foo` може керувати процесом циклу *без* без потреби присвоювати значення будь-яким змінним: він контролює, як часто відбувається цикл, використовуючи дані, що виникають під час розгортання: значення даних, збережені у тимчасових списках токенів. Використовуючи наше знання про застосування TeX (створення) тимчасових списків токенів, ми можемо придивитися ближче, щоб побачити, як саме `\foo` досягає своїх результатів.

**Пам’ятайте**: Ми розбираємо виконання макроса після того, як початковий текст його визначення — що міститься у фізичному `.tex` файлі — був просканований (прочитаний TeX) і перетворений на список токенів, що представляє визначення макроса. По суті, ми стежимо за обробкою TeX цих збережених *токени* поки він читає й обробляє токени у визначенні макроса, що міститься десь у пам’яті TeX. Будь-які символи пробілу, які спочатку були присутні в коді TeX визначення макроса (текст усередині `.tex` файлу), будуть поглинуті під час сканування цього тексту TeX на наявність команд (пробіли як роздільники), або ж вони`,`) у `\ifnum#1<#2,` який виник унаслідок перетворення символу кінця рядка (`\\r`) на пробіл.

Оскільки код TeX у `\foo` використовує кілька `\expandafter` команд, ми полегшимо наше пояснення, додаючи нижні індекси до кожної `\expandafter`, вказуючи, до якої саме ми звертаємося. Крім того, ми розширимо позначення для токенів, оброблюваних `\expandafter` на $$\mathrm{T^i\_1}$$ та $$\mathrm{T^i\_2}$$, представляючи токени $$\mathrm{T\_1}$$ та $$\mathrm{T\_2}$$ для `\expandafter<sub>i</sub>`: `\expandafter<sub>i</sub>` $$\mathrm{T^i\_1T^i\_2}$$

Ось анотований код макроса:

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

`\foo` починається з `\number#1` який використовує розширювану команду `\number` для перетворення значення першого аргументу у його версткове подання. Команда `\number` працює, генеруючи тимчасовий список токенів, що містить символьні токени, які представляють окремі цифри, що входять до числового значення, над яким `\number` він працює. Цей список токенів стає наступним джерелом вводу TeX. Тут цей список токенів читається, а токени виводяться, щоб набрати значення `#1`.

Далі макрос виконує перевірку `\ifnum#1<#2` щоб перевірити, чи аргумент для `#1` є меншим за аргумент, переданий для `#2`. Якщо так, то кома (`,`) виводиться (набирається) токен, після чого йде певний пробіл, що виникає з токена, згенерованого з символу переносу рядка після коми (`,`). Цей символ пробілу вперше був згенерований, коли TeX прочитав цей рядок із `.tex` файлі.

Макрос продовжує обробку наступного фрагмента коду, який є ядром його роботи:

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

По суті, цей код генерує серію тимчасових списків токенів, що призводить до багаторазових викликів `\foo` макроса, і завершується, коли if-перевірка `\ifnum#1<#2` більше не є істинною. Але *як* циклічність керується, оскільки присвоєнь не відбувається: де ж тоді «лічильник циклу»?

Почнімо з розгляду коду `\expandafter<sub>1</sub>\foo\expandafter<sub>2</sub>`. Зверніть увагу, що ми використовуватимемо позначення з нижніми індексами `<sub>token</sub>` (або `<sub>(token)</sub>`) щоб нагадати собі, що тут TeX читає/обробляє числові (цілі) значення токенів.

Тут як вхідні дані для `\expandafter<sub>1</sub>`:

* $$\mathrm{T^1\_1} =$$`\foo<sub>token</sub>` який читається та зберігається для подальшого *повторної вставки* назад у вхід
* $$\mathrm{T^1\_2} =$$`\expandafter<sub>2 (token)</sub>` який розгортається

Для `\expandafter<sub>2</sub>` маємо:

* $$\mathrm{T^2\_1} =$$`{<sub>token</sub>` який зберігається для подальшої *повторної вставки* назад у вхід
* $$\mathrm{T^2\_2} =$$ `\number<sub>token</sub>` який розгортається

**Примітка:**`\number` є розширюваною командою, мета якої — «перетворити на токени»: тобто перетворити числову величину на серію символьних токенів, які представляють цю величину. Коли `\number` вона розгортається, перше, що робить TeX, — сканує вхідні дані в пошуках цілих чисел: процес, який запускає подальше розгортання.

**Ключ до історії:** Тут, `\number` діє на *вираз* `\numexpr#1+1` який обчислює значення `#1+1`. Результат цього обчислення обробляється `\number` для перетворення його на тимчасовий список токенів, що містить символьні токени, які представляють значення `#1 + 1`. Цей тимчасовий список токенів, згенерований `\number`, зрештою буде прочитаний як перший аргумент іншого виклику `\foo`. Замість збільшення лічильника циклу (через `\advance` і присвоєння), використання `\numexpr` створює нове значення, але без потреби в присвоєнні. Завдяки цьому механізму змінна, що керує циклом (`\foo`параметр `#1`) збільшується, а ітерація циклу контролюється й завершується: досить винахідливо!

Далі, `\expandafter<sub>3</sub>` обробляється, даючи:

* $$\mathrm{T^3\_1} =$$`}<sub>token</sub>` який зберігається для подальшої *повторної вставки* назад у вхід
* $$\mathrm{T^3\_2} =$$`\expandafter<sub>4 (token)</sub>`, який розгортається:

Для `\expandafter<sub>4</sub>` маємо:

* $$\mathrm{T^4\_1} =$$`{<sub>token</sub>` який зберігається для подальшої *повторної вставки* назад у вхід
* $$\mathrm{T^4\_2} =$$`\number<sub>token</sub>` який розгортається і перетворює `#2` на ще один тимчасовий список токенів.

Нарешті,`\expandafter<sub>5</sub>` розгортається:

* $$\mathrm{T^5\_1} =$$`}<sub>token</sub>` який зберігається для подальшої *повторної вставки* назад у вхід
* $$\mathrm{T^5\_2} =$$`\fi<sub>token</sub>`, який є розширюваною командою.

  Розгортання `\fi` фактично завершує `\ifnum` і, по суті, закриває цю ітерацію макроса. Тепер TeX завершує повторне вставлення всіх токенів, тимчасово збережених численними `\expandafter` командами: це породжує серію однтокенових списків токенів, що виникають із токенів, збережених кожною `\expandafter`. Крім того, TeX також створив списки токенів з ... завдяки дії `\number`.

### Складання списків токенів

По суті, `\foo` макрос генерує послідовність списків токенів: можна уявляти `\foo` як «виробничу дільницю» списків токенів. Ці списки токенів читаються TeX, щоб стати наступними джерелами вхідних даних. Винахідлива частина міститься в одній із попередніх дій `\foo`:

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

через яку `\foo` влаштовує повторний виклик себе, але з іншими аргументами, які зберігаються у списках токенів, побудованих `\number`. Щоб ці списки токенів спільно поводилися як виклик макроса, фігурні дужки `{` та `}` усі були збережені та повторно вставлені у вхідні дані (як однтокенові списки) завдяки діям `\expandafter` команд.

![списки токенів, згенеровані макросом \foo](/files/ffe9b6ada8a87c28b170dac47ad1cb72c50eee4b)

&#x20;[Частина 1](/latex/uk/dokladni-statti/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)   [Частина 2](/latex/uk/dokladni-statti/22-how-does-expandafter-work-the-meaning-of-expansion.md)   [Частина 3](/latex/uk/dokladni-statti/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md)   [Частина 4](/latex/uk/dokladni-statti/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md)   [Частина 5](/latex/uk/dokladni-statti/17-how-does-expandafter-work-a-detailed-macro-case-study.md)   [Частина 6](/latex/uk/dokladni-statti/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/uk/dokladni-statti/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.
