> 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/ar/mqalat-mtamqh/17-how-does-expandafter-work-a-detailed-macro-case-study.md).

# كيف تعمل \expandafter: دراسة حالة تفصيلية لماكرو

&#x20;[الجزء 1](/latex/ar/mqalat-mtamqh/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)   [الجزء 2](/latex/ar/mqalat-mtamqh/22-how-does-expandafter-work-the-meaning-of-expansion.md)   [الجزء 3](/latex/ar/mqalat-mtamqh/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md)   [الجزء 4](/latex/ar/mqalat-mtamqh/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md)   [الجزء 5](/latex/ar/mqalat-mtamqh/17-how-does-expandafter-work-a-detailed-macro-case-study.md)   [الجزء 6](/latex/ar/mqalat-mtamqh/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)&#x20;

## دراسة حالة: مثال \expandafter من الـ $$\varepsilon\mathrm{\text{-}{\TeX}}$$ الدليل

ال $$\varepsilon\mathrm{\text{-}{\TeX}}$$ محرك التنضيد مستمد من برنامج TeX الخاص بـ Knuth وكان مقصودًا في الأصل كخطوة «مؤقتة» نحو تطوير الـ [نظام التنضيد الجديد](https://en.wikipedia.org/wiki/New_Typesetting_System) (NTS)، المكتوب بلغة البرمجة Java. $$\varepsilon\mathrm{\text{-}{\TeX}}$$ طُوِّر لأول مرة في أواخر التسعينيات لإضافة مجموعة من الأوامر البدائية الجديدة التي توفر وظائف إضافية غير متاحة في البرنامج الأصلي لـ Knuth. وعلى الرغم من أن $$\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` \count99=12345 `99` ليحتوي على القيمة `12345` عبر `. وتحدث أنواع كثيرة أخرى من الإسناد أثناء معالجة TeX — مثل إسناد سجلات الرموز لتحتوي على سلسلة من الرموز، وإسناد سجلات الصناديق لتحتوي على محتوى صناديق، وهكذا.`لإجراء إسناد، مثل

، يحتاج TeX إلى تنفيذ الشفرة الداخلية التي تطبق سلوك `. وتحدث أنواع كثيرة أخرى من الإسناد أثناء معالجة TeX — مثل إسناد سجلات الرموز لتحتوي على سلسلة من الرموز، وإسناد سجلات الصناديق لتحتوي على محتوى صناديق، وهكذا.`أو أي بدائي آخر يُجري نوعًا ما من الإسناد. ومع ذلك، توجد أوقات يكون فيها TeX بصدد إجراء `\count` والتالية، لا تُنفَّذ هذه الإسنادات — *الماكرو* في تلك اللحظة من معالجة Te&#x58;*. ومن أمثلة هذه الحالة الأوامر التالية:*\edef\command {\*token list\*}

* `أمر تعريف الماكرو «التعريف الموسَّع» الذي يوسّع الرموز في` قائمة الرموز *ويخزن النتائج بوصفها تعريف* \command `\write *number* {*token list*}`.
* `يوسّع الرموز في` \*token list\* `ويكتبها في ملف يمثله` \directlua {\*token list\*} `*number*`.
* `يُستخدم هذا الأمر البدائي في LuaTeX لتمرير شيفرة Lua إلى مفسّر Lua المضمَّن. تُوسَّع جميع الرموز في` تُوسَّع بالكامل قبل تمريرها إلى مفسّر Lua للتنفيذ. `ويكتبها في ملف يمثله` مثال سريع على \edef

#### مثال سريع على \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` الماكرو، وتنتهي عندما يصبح اختبار الشرط `\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/16d162623db03f47229f26f567a096fbaa3c70cb)

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