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

# كيف تعمل وحدات TeX الماكرو فعليًا: الجزء 6

[الجزء 1](/latex/ar/mzyd-mn-almwdhwaat/19-how-tex-macros-actually-work-part-1.md) [الجزء 2](/latex/ar/mzyd-mn-almwdhwaat/20-how-tex-macros-actually-work-part-2.md) [الجزء 3](/latex/ar/mzyd-mn-almwdhwaat/21-how-tex-macros-actually-work-part-3.md) [الجزء 4](/latex/ar/mzyd-mn-almwdhwaat/22-how-tex-macros-actually-work-part-4.md) [الجزء 5](/latex/ar/mzyd-mn-almwdhwaat/23-how-tex-macros-actually-work-part-5.md) [الجزء 6](/latex/ar/mzyd-mn-almwdhwaat/24-how-tex-macros-actually-work-part-6.md)

## مقدمة ونظرة عامة: القصة حتى الآن

على مدى الأجزاء الخمسة السابقة من هذه السلسلة رأينا:

* كيف يقرأ TeX الأحرف داخل ملف الإدخال ويستخدم رموز الفئات للتعرّف على «فئات» مختلفة من الأحرف ثم تحويلها إلى رموز حرفية ورموز أوامر؛
* أن الماكرو، في الواقع، يتكوّن من أربعة أقسام:

```
<بدائية ماكرو TeX><اسم الماكرو><نص المعامل>{<نص الاستبدال>}
```

حيث:

* `<بدائية ماكرو TeX>` = أحد `\def`, `\edef`, `\gdef` أو `\xdef`;
* `<اسم الماكرو>`=اسم الماكرو الخاص بك، مثل `\foo`;
* `<نص المعامل>` يمكن أن يكون «فارغًا» (غير موجود) أو يمكن أن يكون سلسلة من رموز الفاصل ورموز معاملات الماكرو؛
* `<نص الاستبدال>` هو الجسم الفعلي لماكروك: القسم الذي يتم «تنفيذه» (توسيعه) عند استدعاء الماكرو.
* كيف أن `<نص المعامل>` يمكن أن يحتوي القسم على طيف واسع من الرموز وأن يستخدمه TeX باعتباره «قالبًا رمزيًا» لمطابقة استدعاء ماكرو بتعريفه الأصلي واستخراج الوسائط المستخدمة مع الماكرو — وكيف يتوقع TeX أن يتطابق استخدامك لماكرو ما مع تعريفه الأصلي؛
* أن تعريف الماكرو داخل TeX يُخزَّن كسلسلة متصلة من الرموز تمثل `<نص المعامل>` و `<نص الاستبدال>` الأقسام.

عندما تستخدم أمر ماكرو، سيتحقق TeX أولًا مما إذا كان يقبل أي معاملات. إذا كان الأمر كذلك، فعلى TeX بعد ذلك أن يحدد *الوسائط* المستخدمة في استدعاء الماكرو الخاص بك. يجب على TeX أن يختبر استدعاء الماكرو مقابل تعريف «القالب الرمزي» الذي خزنه في الذاكرة. وبالتحديد، يستخدم TeX تعريفه الداخلي (المخزن) لـ `<نص المعامل>` القسم كقالب يستطيع من خلاله انتقاء *رموز* التي تمثل الوسائط الفعلية، والتي *رموز* لا توجد إلا لتعمل كفواصل.

## معنى توسيع الماكرو

نحن الآن، أخيرًا، مستعدون للانتقال إلى الموضوع الأهم: كيف يعالج TeX وسائط الماكرو وينفذ الماكرو فعليًا: وهي عملية يشير إليها TeX باسم *توسيع الماكرو*.

### ولكن أولًا، مثال قصير: شيء غريب؟

لتهيئة المشهد لشرح الآلية التي يعالج بها TeX الماكروات ووسائطها، سنستخدم مثالًا قصيرًا للإشارة إلى القضايا التي نحتاج إلى أخذها في الاعتبار.

#### الوسائط تُحوَّل أولًا إلى رموز

يعتمد المثال التالي على مثال نوقش في الصفحتين 114–5 من [كتاب TeX المتقدم](https://www.amazon.co.uk/Advanced-Texbook-David-Salomon/dp/0387945563) من تأليف ديفيد سالومون. وقد تم اختياره لأنه يلخص الأفكار الأساسية في ماكرو TeX قصير جدًا.

أثناء عمليات TeX/LaTeX العادية، فإن `$` العلامة لها رمز فئة 3 («تحويل رياضي») والذي يُدخل TeX إلى/يخرجه من وضع الرياضيات داخل السطر (`$...$`) أو وضع الرياضيات المعروضة (`$$...$$`) — وبالطبع يستخدم LaTeX `\(..\)` و `\[..\]` لنفس الأغراض.

لنفترض أننا نريد ماكروًا يغيّر رمز فئة علامة `$` الدولار، مثلًا، إلى 11 حتى نتمكن من تنضيدها كأي حرف عادي. يمكننا استخدام الأمر البدائي في TeX `\catcode` وكانت محاولتنا الأولى لمثل هذا الماكرو، `\docat`، قد تكون

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

لكن عندما نحاول استخدامه، هكذا

```
\begin{document}
\def\docat #1{\catcode`\$=11 #1}
دفعتُ \docat{$90} مقابل ذلك الكتاب.
\end{document}
```

نتوقع أن يقوم TeX بتنضيد `دفعتُ $90 مقابل ذلك الكتاب.` لكن الأمر يفشل برسالة خطأ:

```
! تم إدراج $ مفقود.
<نص مُدرَج>
                $
<ليُقرأ مرة أخرى>
                   \par
l.7
```

من رسالة الخطأ يبدو أن `$` المستخدم في وسيط الماكرو ما يزال يدفع TeX إلى تنضيد الرياضيات؛ من الواضح أن TeX *لم* يغيّر رمز الفئة لـ `$` المستخدم في وسيط الماكرو لدينا (`$90`). والسؤال هو *لماذا* لماذا لم يغيّر TeX رمز الفئة لـ `$` إلى 11 وينضّدها كحرف عادي؟ الإجابة المختصرة هي أن TeX يحول وسائط الماكرو أولًا إلى رموز **قبل أن** ثم يمررها إلى قائمة الرموز الخاصة بـ `<نص الاستبدال>`— لكننا سننظر إلى الآليات الكامنة بتفصيل أكبر بكثير.

ما علينا أن نتذكره هو أن تصورنا لاستخدام TeX للنص/الأحرف لا يهم إلا لمحتوى الملف الذي يقرأه TeX: فبمجرد أن يقرأ TeX أي أحرف ندخل إلى عالم *رموز*. تعمل استدعاءات ماكرو TeX مع *رموز*، وليس مع *التمثيل المكتوب/النصي* لأوامر TeX/LaTeX — وسيتضح هذا أكثر أثناء استعراض المثال.

في البداية قد نعتقد أن استخدامنا لـ `\docat` الماكرو في `دفعتُ \docat{$90} مقابل ذلك الكتاب.` هو نفسه كتابة كود TeX (أو LaTeX) المكافئ مباشرةً — مثل التالي، والذي *لا* يعمل:

```
\begin{document}
دفعتُ \catcode`\$=11 $90 مقابل ذلك الكتاب.
\end{document}
```

![بعض كود TeX يعمل على Overleaf](/files/a4ab69c1a21e19a83195c7e7895fb9faeeae8366)

لكن، كما رأينا أعلاه، فإن الطريقة التي يعالج بها TeX وسائط الماكرو تنتج نتيجة (`! تم إدراج $ مفقود.`) *لماذا* مما يحدث.

### الماكروات والوسائط كقوائم رمزية

لفهم سلوك `\docat` الماكرو، ووسيطه (`$90`)، ولماذا يفشل، نحتاج مرة أخرى إلى تصور تعريف `\docat` الماكرو وأي وسائط مستخدمة (عند استدعاء \docat) على أنها *قوائم من الرموز*، وليس كسلسلة من الأحرف.

أثناء مسح TeX لنص الإدخال، سيتعرف على `\docat` كأمر ماكرو؛ وبعد ذلك يتحقق مما إذا كان يقبل أي معاملات — وكيف يقوم TeX بذلك موضح في القسم التالي للقراء المهتمين بالتفاصيل الدقيقة.

#### لمن يحبون التفاصيل...

بعد استدعاء الماكرو، يتحقق TeX مما إذا كان الرمز الأول جدًا (في قائمة رموز تعريف الماكرو المخزنة) هو **رمز نهاية المطابقة** ؛ فإذا كان الأمر كذلك، يمكن لـ TeX أن يتيقن من أن الماكرو لا يأخذ أي معاملات.

**مثال**

تقارن مخططات قائمة العقد التالية قوائم الرموز لماكروين:

* `\def\foo A#1B{#1}`؛ يحتوي هذا على `<نص المعامل>` لـ `A#1B`، وبالتالي فإن **رمز نهاية المطابقة** الرمز هو **تحتوي** الرمز الأول، لذلك سيشرع TeX في البحث عن معاملات؛
* `\def\foo{X}`؛ لا يحتوي هذا على `<نص المعامل>` قسم، وبالتالي فإن **رمز نهاية المطابقة** الرمز هو الأول في قائمة الرموز ويعرف TeX ألا يبحث عن أي معاملات.

![كيف يتحقق TeX مما إذا كان الماكرو يأخذ معاملات](/files/690d9ce463300fe3897541e250030c8f3166c05a)

## نحو «الختام الكبير»: التوسيع

لِنُذكِّر أنفسنا بالسؤال: لماذا لم يعمل الماكرو التالي؛ أي لماذا لا يغيّر TeX رمز الفئة لأي `$` من علامات الدولار المستخدمة في وسيط `\docat` الماكرو، مثل `\docat{$90}`?

```
\begin{document}
\def\docat #1{\catcode`\$=11 #1}
دفعتُ \docat{$90} مقابل ذلك الكتاب.
\end{document}
```

كما أوضحنا أعلاه، عندما يمسح TeX إدخالك ويتعرف على أمر ماكرو — في الوقت الذي سيقوم فيه TeX بتنفيذه — فإنه يتحقق أولًا مما إذا كان ذلك الماكرو يأخذ أي معاملات. إذا كان الأمر كذلك، فسيحتاج TeX إلى مواصلة مسح ملف الإدخال لتحديد *الوسائط* التي قدمها المستخدم لهذا الاستدعاء المحدد للماكرو: يجب على TeX فعل ذلك **قبل أن** قبل أن يتمكن من استدعاء الشيفرة الفعلية للماكرو. من الواضح أن TeX يحتاج إلى تحديد البيانات التي يريد المستخدم تقديمها للماكرو.

وللتعرّف على الوسائط الموجودة في الإدخال (استدعاء الماكرو الخاص بالمستخدم)، يسترشد TeX بالتعريف المخزن داخليًا لذلك الماكرو: وبالتحديد، `<نص المعامل>` القسم من تعريف الماكرو المخزن (قائمة الرموز) — الذي يوفر نوعًا من «القالب الرمزي». وباستخدام ذلك «القالب الرمزي» على TeX أن يحدد أي *رموز* في استدعاء الماكرو الخاص بالمستخدم ليست سوى *الفواصل* (أي «علامات ترقيم» أساسًا) وأيها *رموز* تشكل جزءًا من *وسيط*. وعندما يواجه TeX رمز **معامل المطابقة** في تعريف الماكرو المخزن `<نص المعامل>` القسم («القالب الرمزي») فإنه يعرف أنه يجب أن يبدأ بتكوين *قائمة من الرموز* لهذا الوسيط بعينه.

فور أن يدرك TeX الحاجة إلى تحديد وسيط المستخدم، يمسح الإدخال لتوليد رموز ويفحصها بعناية شديدة، رمزًا رمزًا، مقابل تعريف الماكرو المخزن. ويواصل TeX جمع الرموز لوسيط ما حتى يكتشف رمزًا هو في الواقع فاصلًا، أو إذا اكتشف **رمز نهاية المطابقة** الرمز: في كلتا الحالتين، يعرف TeX عندئذٍ أن الوقت قد حان للتوقف عن البحث عن الرموز التي تشكل جزءًا من ذلك الوسيط.

### لماذا فشل الماكرو \docat

كما أُشير، *قبل أن* حتى يتمكن TeX فعليًا من استدعاء ماكرو، عليه أن يحدد أي وسائط ستُستخدم مع ذلك الماكرو ويُحضِّرها. لكن لتحديد الوسيط/الوسائط، وجاهزة لإدخالها في الماكرو، يجب على TeX أن يولّد كل وسيط على هيئة *قائمة من الرموز*؛ وهذا هو السبب في `\docat`فشل

في مثالنا، قدمنا `\docat` لـ `$90` لكن ذلك الوسيط يُحوَّل أولًا *إلى قائمة من الرموز* أثناء مسح TeX لاستدعاء الماكرو — حيث يُحوَّل الوسيط إلى رموز *قبل أن* قبل أن يُستدعى الماكرو فعليًا. هنا، بالنسبة للوسيط `$90`، سيولِّد TeX ثلاثة رموز حرفية: رمزًا واحدًا لكلٍ من `$`, `9` و `0`.

يوضح الرسم التالي قائمة الرموز المولدة للوسيط `$90`، قبل تمريرها إلى جسم `\docat` الماكرو:

![قائمة رموز TeX المولدة لوسيط ماكرو](/files/85b3b5cf5f293dfa88ae277b4fbe5afb82312cd1)

في الرسم أعلاه يمكننا أن نرى بوضوح أن قائمة رموز الوسيط تحتوي على `$` كـرمز حرفي استنادًا إلى رمز فئة 3.

كما رأينا في الأجزاء 1 إلى 3، تُنشأ الرموز الحرفية باستخدام قيم رمز الفئة *السارية في اللحظة التي يُقرأ فيها الحرف*— أي في الوقت الذي تُنشأ فيه قائمة رموز الوسيط (أي تُحوَّل إلى رموز). وفي الوقت الذي تُرمَّز فيه الوسائط، فإن `\docat` الماكرو لم يُنفَّذ بعد، لذا فإن تغيير رمز الفئة الذي وضعناه في استدعاء الماكرو (``\catcode`\$=11``) *لا* لا يؤثر في رموز الفئة المستخدمة لتوليد رموز الوسيط.

بمجرد أن يكون TeX قد ولّد قائمة رموز تمثل وسيط `$90`، تُمرَّر هذه الرموز الحرفية الثلاثة إلى الماكرو الفعلي `<نص الاستبدال>`؛ لكن ذلك يؤدي إلى أن `$` يُمرَّر على هيئة *رمزًا مميزًا للحرف* مُنشأ باستخدام رمز الفئة 3: «تشغيل الرياضيات»، وقد رأينا أنه ما إن يتكوّن الرمز الحرفي حتى يصبح رمز الفئة المرفق به دائمًا. إن `$` هو *تحتوي* الذي يُمرَّر إلى الماكرو *كحرف*، بل كـ *رمزًا مميزًا للحرف* استنادًا إلى `$` كونه يحمل رمز الفئة 3.

### تنفيذ \docat: توسيع الماكرو

يشير TeX إلى عملية «تنفيذ» *توسيع الماكرو*؛ وهو مصطلح، في رأي هذا المؤلف، مربك بعض الشيء لكنه المصطلح المتعارف عليه لذا سنواصل استخدامه.

#### المعنى الحقيقي لتوسيع الماكرو

بعد أن يكتشف TeX `\docat` الأمر في إدخال المستخدم، يمسح الوسائط ويولّد قائمة رموز لوسيطه(`$90`). ولتنفيذ (توسيع) الماكرو، يحوّل TeX نظره بعيدًا عن ملف إدخال المستخدم ويبدأ بقراءة الرموز الموجودة `\docat`لـ `<نص الاستبدال>` في قائمة الرموز المخزنة في ذاكرة TeX.

أثناء معالجة TeX لـ `\docat`تعريفه، سيرى بعد ذلك سلسلة الرموز التي استُخدمت أصلًا لتعريف الماكرو (`**catcode**`, ``**`**``, `**\$**`, `**=**`, `**1**`, `**1**`, `**#1**`).

يوضح الرسم التالي عملية توسيع `\docat` الماكرو: يتوقف TeX عن جلب الرموز من ملف الإدخال ويبدأ بقراءة الرموز من `<نص الاستبدال>` القسم الخاص بـ `\docat` تعريف الماكرو المخزن في الذاكرة. يواصل TeX تنفيذ هذه الرموز المعدّة مسبقًا حتى يرى **معامل الإخراج** رمزًا يوجّه TeX إلى قراءة («إدخال») رموز الوسيط و«تنفيذها» في هذه النقطة. في مثالنا، تلك هي ثلاثة رموز حرفية تمثل `$90` وذلك يؤدي إلى خطأ لأن الرمز الحرفي المُعد مسبقًا لـ `$` يحمل رمز الفئة 3. ولأننا نتعامل مع رموز حرفية لا مع أحرف، فإن `$` لا يتأثر بتغيير رمز الفئة السابق الناتج عن الرموز الموجودة في ``\catcode`\$=11``.

![عرض عملية توسيع الماكرو \docat](/files/27f8df5e3812808e56d89ae561840490b8e40032)

بعد أن يعالج TeX الرموز التي تمثل ``\catcode`\$=11``، يصبح تغيير رمز الفئة لـ `$` ساري المفعول الآن. ثم يواجه TeX «الرمز الخاص» المسمى **معامل الإخراج** الذي يخبر TeX بأن **بإدراج** قائمة الرموز الخاصة بالوسيط. لكن تلك القائمة تتكون من ثلاثة رموز حرفية *رموز*، أولها رمز لـ `$` مع إسناد رمز فئة 3 («تشغيل الرياضيات») إليه: لا يستطيع تغيير رمز الفئة السابق داخل الماكرو أن يؤثر في هذا الرمز الحرفي، لذلك يعامله TeX كإشارة لبدء معالجة الرياضيات، وهذا يؤدي إلى فشل الماكرو.

### هل يمكن إصلاح الماكرو \docat؟

من المناقشات أعلاه، يتضح أن أي أحرف تظهر في وسائط الماكرو تُحوَّل إلى رموز باستخدام رموز الفئة السارية في وقت حدوث التحويل — والذي، في مثالنا، هو *دائمًا* قبل أن `<نص الاستبدال>` في `\docat` يُنفَّذ الماكرو فعليًا. إذًا كيف يمكننا ضمان تغيير رموز الفئة لوسائط الماكرو؟

إحدى الطرق هي تعديل `\docat` ليكون ماكروًّا بلا معاملات يقتصر فقط على إجراء تغيير رمز الفئة — فهو لا يملك أي وسائط ليحوّلها إلى رموز. ثم نستخدم ماكروًا ثانيًا، `\getarg`، يأخذ معاملًا واحدًا، ونرتّب بحيث يُحوَّل وسيطه إلى رموز عندما يكون رمز الفئة المناسب لـ `$` ساري المفعول.

```
\begin{document}
\def\docat{\catcode`\$=11 \getarg} % لا معاملات، يستدعي ماكروًا ثانيًا \getarg
\def\getarg#1{#1} % معامل واحد سيُحوَّل وسيطه إلى رموز
الآن يمكنك تشغيله هكذا وسيعمل:

دفعتُ \docat{$90} مقابل ذلك الكتاب.
\end{document}
```

عندما نستخدم النسخة الجديدة من `\docat` (هكذا `\docat{$90}`) فإنه *يبدو* كما لو أن `$90` لا يزال يُستخدم كوسيط لـ `\docat` الماكرو. لكن، كما نوقش أعلاه، عندما يكتشف TeX `\docat` في الإدخال يتحقق مما إذا كان له أي وسائط: الآن لم يعد له، لذا يشرع TeX في تنفيذه (توسيعه). إن توسيع `\docat` هو تسلسل الرموز `**catcode**`, ``**`**``, `**\$**`, `**=**`, `**1**`, `**1**`, `**space**`, `**getarg**` ويحدث هذا *قبل أن* عندما يبدأ TeX بقراءة (ترميز) الأحرف التالية الموجودة في ملف الإدخال — أي المجموعة `{$90}`. تذكّر أنه عندما يوسّع TeX ماكروًا فإنه يحصل على مدخله التالي بقراءة الرموز الموجودة في قائمة الرموز الخاصة بتعريف ذلك الماكرو؛ أي من `<نص الاستبدال>` القسم المخزن في الذاكرة.

سيعالج TeX توسيع `\docat` ويكتشف *الرمز* **`getarg`**، معترفًا به كرمز يمثل أمرًا يأخذ معاملات. عند هذه النقطة، سيفحص TeX ملف الإدخال بحثًا عن **`getarg`**&#x648;سيطه: الأحرف: `{$90}`. كالمعتاد، تُحوَّل هذه إلى رموز، لكن لأن TeX قد قرأ وعالج توسيع `\docat`، فإن الأحرف `$90` تُحوَّل إلى رموز عندما يكون رمز الفئة لـ `$` قد تغيّر إلى 11. والتعريف (`<نص الاستبدال>`) الخاص بـ `\getarg` هو ببساطة `#1` وذلك يعني تنضيد الوسيط المُعطى، وهذا ما يحدث بالفعل، مما ينتج عنه `$` توليد حرف برمز فئة 11 وتنضيده بأمان.

## ملاحظات ختامية: القصة في العقد

تسلسل الأحداث الناتج عن إعادة كتابة `\docat` لاستخدام الماكرو `\getarg` موجود في مخطط قائمة العقد المشروح التالي الذي يوضح عملية توسيع الماكرو `\docat`. يمكن للقراء الراغبين في دراسة هذا المخطط بعناية تنزيل الرسم بوصفه ملف [PDF](https://assets.ctfassets.net/nrgyaltdicpt/7MOBdavza4WxAEQGISEEht/cabe5097d9063a6415bc553cd38237e6/newdocatexpansion.pdf) أو [SVG](https://images.ctfassets.net/nrgyaltdicpt/2FIqqVRXjakdAzTpZsV0m9/10ccc1353741d42d3df18f1692d8aa84/newdocatexpansion--plain.svg) لاستخدامه دون اتصال.

![عرض عملية توسيع الماكرو \docat المعدّل وماكرو \getarg](/files/448032d6b84de90e59b3b7a2fb385d5f879bb0de)

[الجزء 1](/latex/ar/mzyd-mn-almwdhwaat/19-how-tex-macros-actually-work-part-1.md) [الجزء 2](/latex/ar/mzyd-mn-almwdhwaat/20-how-tex-macros-actually-work-part-2.md) [الجزء 3](/latex/ar/mzyd-mn-almwdhwaat/21-how-tex-macros-actually-work-part-3.md) [الجزء 4](/latex/ar/mzyd-mn-almwdhwaat/22-how-tex-macros-actually-work-part-4.md) [الجزء 5](/latex/ar/mzyd-mn-almwdhwaat/23-how-tex-macros-actually-work-part-5.md) [الجزء 6](/latex/ar/mzyd-mn-almwdhwaat/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/ar/mzyd-mn-almwdhwaat/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.
