المُكرِّر
في برمجة الحاسوب ، يُعدّ المُكرِّر كائنًا يُتيح الوصول تدريجيًا إلى كل عنصر من عناصر المجموعة ، بالترتيب. [ 1 ] [ 2 ] [ 3 ]
قد توفر المجموعة عدة مكررات عبر واجهتها والتي توفر العناصر بترتيبات مختلفة، مثل الترتيب الأمامي والخلفي.
غالبًا ما يتم تنفيذ المكرر من حيث البنية الأساسية لتنفيذ المجموعة، وغالبًا ما يكون مرتبطًا ارتباطًا وثيقًا بالمجموعة لتمكين الدلالات التشغيلية للمكرر.
المكرر يشبه سلوكياً مؤشر قاعدة البيانات .
يعود تاريخ المكررات إلى لغة البرمجة CLU في عام 1974. [ 4 ]
نمط
يُتيح المُكرِّر الوصول إلى عنصرٍ من عناصر المجموعة ( الوصول إلى العنصر )، ويُمكنه تغيير حالته الداخلية للوصول إلى العنصر التالي ( اجتياز العنصر ). [ 5 ] كما يُتيح إنشاء العنصر الأول وتهيئته، ويُشير إلى ما إذا كان قد تم اجتياز جميع العناصر. في بعض سياقات البرمجة، يُوفر المُكرِّر وظائف إضافية.
يُمكّن المُكرِّر المُستخدِم من معالجة كل عنصر من عناصر المجموعة مع عزله عن البنية الداخلية للمجموعة. [ 2 ] يمكن للمجموعة تخزين العناصر بأي طريقة، بينما يمكن للمُستخدِم الوصول إليها كسلسلة.
في البرمجة الكائنية التوجه، عادةً ما يتم تصميم فئة المُكرِّر بالتنسيق الوثيق مع فئة المجموعة المقابلة. وعادةً ما توفر المجموعة طرقًا لإنشاء المُكرِّرات.
يُشار أحيانًا إلى عداد الحلقات باسم مُكرِّر الحلقات. مع ذلك، لا يوفر عداد الحلقات سوى وظيفة اجتياز الحلقات، وليس وظيفة الوصول إلى العناصر.
مولد
إحدى طرق تنفيذ المُكرِّر هي عبر شكل مُقيَّد من الروتين الفرعي ، يُعرف باسم المُولِّد . على عكس الروتين الفرعي ، يُمكن لروتين المُولِّد الفرعي أن يُعيد قيمًا إلى مُستدعيه عدة مرات، بدلًا من إعادتها مرة واحدة فقط. يُمكن التعبير عن مُعظم المُكرِّرات بشكل طبيعي كمُولِّدات، ولكن نظرًا لأن المُولِّدات تحتفظ بحالتها المحلية بين الاستدعاءات، فهي مُناسبة بشكل خاص للمُكرِّرات المُعقدة التي تحتفظ بحالة، مثل مُجتازي الأشجار . توجد اختلافات دقيقة في استخدام مصطلحي "المُولِّد" و"المُكرِّر"، والتي تختلف بين المُطورين واللغات. [ 6 ] في بايثون ، المُولِّد هو مُنشئ مُكرِّر : دالة تُعيد مُكرِّرًا. فيما يلي مثال على مُولِّد بايثون يُعيد مُكرِّرًا لأعداد فيبوناتشيyield باستخدام عبارة بايثون :
من typing استورد Generatorدالة فيبوناتشي ( الحد : عدد صحيح ) -> مولد [ عدد صحيح ، لا شيء ، لا شيء ]: a ، b = 0 ، 1 لكل _ في نطاق ( الحد ): إرجاع a a ، b = b ، a + bfor number in fibonacci ( 100 ): # يقوم المولد بإنشاء مُكرِّر print ( number )المكرر الداخلي
المُكرِّر الداخلي هو دالة من الرتبة العليا (غالباً ما تستخدم دوالاً مجهولة ) تجتاز مجموعةً وتُطبِّق دالة على كل عنصر. على سبيل المثال، mapتُطبِّق دالة بايثون دالة مُعرَّفة من قِبل المُستدعي على كل عنصر:
من typing استورد Iteratorالأرقام : قائمة [ عدد صحيح ] = [ 0 ، 1 ، 2 ، 3 ، 4 ، 5 ، 6 ، 7 ، 8 ، 9 ]squared_digits : Iterator [ int ] = map ( lambda x : x ** 2 , digits ) # التكرار على هذا المكرر سينتج عنه 0، 1، 4، 9، 16، ...، 81.المُكرِّر الضمني
تُوفّر بعض لغات البرمجة كائنية التوجه، مثل C# و C++ (الإصدارات الأحدث) و Delphi (الإصدارات الأحدث) و Go و Java (الإصدارات الأحدث) و Lua و Perl و Python و Ruby، طريقةً مُدمجةً للتكرار عبر عناصر مجموعة دون الحاجة إلى مُكرِّر صريح. قد يكون كائن المُكرِّر موجودًا، ولكنه غير مُمثَّل في شفرة المصدر. [ 5 ] [ 7 ]
غالباً ما يظهر المُكرِّر الضمني في بناء جملة اللغة على النحو التالي foreach: .
في لغة بايثون، يمكن تكرار عناصر مجموعة البيانات مباشرةً:
for value in iterable : print ( value )في لغة روبي، تتطلب عملية التكرار الوصول إلى خاصية المُكرِّر:
لكل عنصر قابل للتكرار ، نفّذ | القيمة | وضع القيمة .يُطلق على أسلوب التكرار هذا أحيانًا اسم "التكرار الداخلي" لأن الكود الخاص به يتم تنفيذه بالكامل ضمن سياق الكائن القابل للتكرار (الذي يتحكم في جميع جوانب التكرار)، ولا يقدم المبرمج سوى العملية المراد تنفيذها في كل خطوة (باستخدام دالة مجهولة ).
قد تستخدم اللغات التي تدعم تراكيب القوائم أو البنى المشابهة أيضًا المكررات الضمنية أثناء إنشاء قائمة النتائج، كما هو الحال في لغة بايثون:
الأسماء : قائمة [ نص ] = [ اسم الشخص لكل شخص في القائمة إذا كان الشخص ذكرًا ]أحيانًا يكون الإخفاء الضمني جزئيًا فقط. تحتوي لغة C++ على بعض قوالب الدوال للتكرار الضمني، مثل for_each()`. تتطلب هذه الدوال كائنات تكرار صريحة كمدخلات أولية، لكن التكرار اللاحق لا يُظهر كائن التكرار للمستخدم.
تدفق
تُعدّ المُكرِّرات تجريدًا مفيدًا لتدفقات الإدخال ، إذ تُوفّر كائنًا قابلًا للتكرار (وإن لم يكن بالضرورة قابلًا للفهرسة) لا نهائيًا. تُنفّذ العديد من اللغات، مثل بيرل وبايثون، التدفقات باستخدام المُكرِّرات. في بايثون، تُمثّل المُكرِّرات كائنات تُمثّل تدفقات البيانات. [ 8 ] تشمل التطبيقات البديلة للتدفق لغات تعتمد على البيانات ، مثل AWK و sed .
قارن بالفهرسة
بدلاً من استخدام المُكرِّر، تسمح العديد من اللغات باستخدام عامل الفهرسة وعداد الحلقة للوصول إلى كل عنصر. على الرغم من إمكانية استخدام الفهرسة مع المجموعات، إلا أن استخدام المُكرِّرات قد يكون له مزايا مثل: [ 9 ]
- لا تُعد حلقات العد مناسبة لجميع هياكل البيانات، وخاصة هياكل البيانات التي لا تحتوي على وصول عشوائي أو تحتوي على وصول عشوائي بطيء ، مثل القوائم أو الأشجار .
- يمكن أن توفر المكررات طريقة متسقة للتكرار على هياكل البيانات من جميع الأنواع، وبالتالي تجعل الكود أكثر قابلية للقراءة وإعادة الاستخدام وأقل حساسية للتغيير في بنية البيانات .
- يمكن للمكرر أن يفرض قيودًا إضافية على الوصول، مثل ضمان عدم إمكانية تخطي العناصر أو عدم إمكانية الوصول إلى عنصر تمت زيارته سابقًا مرة ثانية.
- قد يسمح المُكرِّر بتعديل كائن المجموعة دون إبطال المُكرِّر. على سبيل المثال، بمجرد أن يتجاوز المُكرِّر العنصر الأول، قد يكون من الممكن إدراج عناصر إضافية في بداية المجموعة بنتائج متوقعة. مع الفهرسة، يُصبح هذا الأمر إشكاليًا لأن أرقام الفهرس يجب أن تتغير.
أصبحت إمكانية تعديل المجموعة أثناء المرور على عناصرها ضرورية في البرمجة الكائنية الحديثة ، حيث قد لا تكون العلاقات المتبادلة بين الكائنات وتأثيرات العمليات واضحة. باستخدام المُكرِّر، يتم تجنب هذه التبعات. مع ذلك، يجب التعامل مع هذا الادعاء بحذر، لأنه في أغلب الأحيان، ولأسباب تتعلق بالكفاءة، يكون تطبيق المُكرِّر مرتبطًا ارتباطًا وثيقًا بالمجموعة لدرجة أنه يمنع تعديل المجموعة الأساسية دون إبطالها.
بالنسبة للمجموعات التي قد تنقل بياناتها في الذاكرة، فإن الطريقة الوحيدة لتجنب إبطال المُكرِّر هي أن تحتفظ المجموعة بسجل لجميع المُكرِّرات النشطة حاليًا وتُحدِّثها بشكل فوري. ونظرًا لأن عدد المُكرِّرات في أي وقت قد يكون كبيرًا جدًا مقارنةً بحجم المجموعة المرتبطة، فإن تحديثها جميعًا سيؤثر سلبًا على ضمان التعقيد لعمليات المجموعة.
يتمثل أحد البدائل للحفاظ على عدد التحديثات مرتبطًا بحجم المجموعة في استخدام آلية معالجة، أي مجموعة من المؤشرات غير المباشرة لعناصر المجموعة التي يجب تحديثها مع المجموعة، وجعل المُكرِّرات تشير إلى هذه المؤشرات بدلًا من الإشارة مباشرةً إلى عناصر البيانات . إلا أن هذا الأسلوب سيؤثر سلبًا على أداء المُكرِّر، إذ يتطلب تتبع مؤشرين للوصول إلى عنصر البيانات الفعلي. وهذا غير مرغوب فيه عادةً، لأن العديد من الخوارزميات التي تستخدم المُكرِّرات تستدعي عملية الوصول إلى البيانات الخاصة بها أكثر من الطريقة المتقدمة. لذا، من الأهمية بمكان أن تتمتع المُكرِّرات بكفاءة عالية في الوصول إلى البيانات.
باختصار، يمثل هذا الأمر دائمًا مفاضلة بين الأمان (حيث تظل المؤشرات صالحة دائمًا) والكفاءة. في أغلب الأحيان، لا يُبرر الأمان الإضافي التضحية بالكفاءة. يُعد استخدام مجموعة بديلة (مثل قائمة مرتبطة أحادية بدلًا من متجه) خيارًا أفضل (وأكثر كفاءة على مستوى النظام) إذا كانت هناك حاجة إلى استقرار المؤشرات.
تصنيف
فئات
يمكن تصنيف أدوات التكرار وفقًا لوظائفها. فيما يلي قائمة (غير شاملة) لفئات أدوات التكرار: [ 10 ] [ 11 ]
| فئة | اللغات |
|---|---|
| مكرر ثنائي الاتجاه | C++ ، Rust [ 12 ] |
| المُكرِّر الأمامي | لغة سي++ |
| مُكرِّر الإدخال | لغة سي++ |
| مُكرِّر الإخراج | لغة سي++ |
| مُكرِّر الوصول العشوائي | لغة سي++ |
| مُكرِّر تافه | C++ ( STL القديمة ) [ 13 ] |
الأنواع
تُعرّف أنواع المُكرِّرات بواسطة لغات أو مكتبات مختلفة تُستخدم مع هذه اللغات. بعضها [ 14 ]
| يكتب | اللغات |
|---|---|
| مُكرِّر المصفوفة | PHP ، R [ 15 ] |
| مُكرِّر التخزين المؤقت | PHP |
| مُكرِّر ثابت | C++ ، [ 16 ] PHP |
| مُكرِّر الدليل | PHP، بايثون |
| مُكرِّر التصفية | PHP، R |
| محدد التكرار | PHP |
| مُكرِّر القائمة | سي شارب ، جافا ، [ 7 ] آر |
| مُكرِّر المصفوفة التكراري | PHP |
| مُكرِّر XML | PHP |
في لغات البرمجة المختلفة
.شبكة
تُسمى المُكرِّرات في إطار عمل .NETIEnumerator (أي C#) "المُعدِّدات" ويتم تمثيلها بواسطة الواجهة. [ 17 ] : 189-190، 344 [ 18 ] : 53-54IEnumerator تُوفر MoveNext()طريقةً للانتقال إلى العنصر التالي وتُشير إلى ما إذا تم الوصول إلى نهاية المجموعة؛ [ 17 ] : 344 [ 18 ] : 55-56 [ 19 ] : 89 خاصيةً Currentللحصول على قيمة العنصر الذي يُشير إليه المؤشر حاليًا؛ [ 17 ] : 344 [ 18 ] : 56 [ 19 ] : 89 وطريقةً اختياريةً Reset()، [ 17 ] : 344 لإعادة المُعدِّد إلى موضعه الأولي. يُشير المُعدِّد في البداية إلى قيمة خاصة قبل العنصر الأول، لذا يلزم استدعاء هذه الطريقة MoveNext()لبدء التكرار.
عادةً ما يتم الحصول على المُعدِّدات باستدعاء GetEnumerator()دالة كائن يُطبِّق الواجهة IEnumerable. [ 18 ] : 54-56 [ 19 ] : 54-56 خاصية Current، للحصول على قيمة العنصر الذي يُشار إليه حاليًا؛ [ 17 ] : 344 [ 18 ] : 56 [ 19 ] : 89 تُطبِّق فئات الحاويات عادةً هذه الواجهة. مع ذلك، يمكن لعبارة foreach في لغة C# أن تعمل على أي كائن يُوفِّر مثل هذه الدالة، حتى لو لم يُطبِّقها IEnumerable( الكتابة الديناميكية ). [ 19 ] : 89 تم توسيع كلتا الواجهتين إلى إصدارات عامة في .NET 2.0 .
يوضح المثال التالي استخدامًا بسيطًا للمكررات في لغة C# 2.0:
باستخدام System ؛ باستخدام System.Collections.Generic ؛// نسخة صريحة IEnumerator <MyType> iter = list.GetEnumerator ( ) ; while ( iter.MoveNext ( ) ) { Console.WriteLine ( iter.Current ) ; }// النسخة الضمنية foreach ( MyType value in list ) { Console . WriteLine ( value ); }يدعم C# 2.0 أيضًا المولدات : الطريقة التي يتم تعريفها على أنها تُرجع IEnumerator(أو IEnumerable)، ولكنها تستخدم yield returnعبارة " " لإنتاج سلسلة من العناصر بدلاً من إرجاع مثيل كائن، سيتم تحويلها بواسطة المترجم إلى فئة جديدة تُنفذ الواجهة المناسبة.
ج
لا توجد المكررات بشكل أصلي في لغة C ، ولكن يمكن محاكاتها إلى حد ما باستخدام حساب المؤشرات .
يوضح المثال التالي قائمة مرتبطة intمع مُكرِّر.
typedef struct LinkedList { int * value ; struct LinkedList * next ; } LinkedList ;typedef struct { LinkedList * current ; } LinkedListIterator ;LinkedListIterator list_begin ( LinkedList * head ) { LinkedListIterator it = { head }; return it ; }int * list_next ( LinkedListIterator * it ) { if ( ! it -> current ) { return NULL ; } int * value = & it -> current -> value ; it -> current = it -> current -> next ; return value ; }int main () { // ... for ( LinkedListIterator it = list_begin ( head ); ; ) { int * val = list_next ( & it ); if ( ! val ) { break ; } printf ( "%d \n " , * val ); } }لغة سي++
تستخدم لغة C++ المُكرِّرات على نطاق واسع في مكتبتها القياسية ، وتصف عدة فئات منها تختلف في نطاق العمليات التي تسمح بها. تشمل هذه الفئات المُكرِّرات الأمامية ، والمُكرِّرات ثنائية الاتجاه ، ومُكرِّرات الوصول العشوائي ، مرتبةً حسب تزايد إمكانياتها. توفر جميع أنواع قوالب الحاويات القياسية مُكرِّرات من إحدى هذه الفئات. تُعمِّم المُكرِّرات المؤشرات إلى عناصر المصفوفة (والتي يمكن استخدامها بالفعل كمُكرِّرات)، وقد صُمِّم تركيبها ليُشابه تركيب حساب المؤشرات في لغة C ، حيث تُستخدم المعاملات ` and` للإشارة إلى العنصر الذي يُشير إليه المُكرِّر، وتُستخدم معاملات حساب المؤشرات `x` و`y` لتعديل المُكرِّرات أثناء اجتياز الحاوية.*->++
تتضمن عملية اجتياز النطاق باستخدام المُكرِّرات عادةً مُكرِّرًا واحدًا متغيرًا، ومُكرِّرين ثابتين يُستخدمان لتحديد نطاق النطاق المراد اجتيازه. المسافة بين المُكرِّرين، من حيث عدد مرات تطبيق المُعامل ++اللازم لتحويل الحد الأدنى إلى الحد الأعلى، تُساوي عدد العناصر في النطاق المُحدد؛ وعدد قيم المُكرِّر المختلفة يزيد بواحد عن ذلك. اصطلاحًا، يُشير المُكرِّر الأدنى إلى العنصر الأول في النطاق، بينما لا يُشير المُكرِّر الأعلى إلى أي عنصر في النطاق، بل إلى ما بعد نهايته مباشرةً. لاجتياز حاوية كاملة، begin()تُوفر الدالة الحد الأدنى والحد end()الأعلى. لا يُشير الحد الأعلى إلى أي عنصر من عناصر الحاوية، ولكنه قيمة مُكرِّر صالحة يُمكن مُقارنتها.
يوضح المثال التالي استخدامًا نموذجيًا للمكرر.
استيراد std ؛باستخدام std :: vector ;int main () { vector < int > items ; items . push_back ( 5 ); // إضافة القيمة العددية '5' إلى المتجه 'items'. items . push_back ( 2 ); // إضافة القيمة العددية '2' إلى المتجه 'items'. items . push_back ( 9 ); // إضافة القيمة العددية '9' إلى المتجه 'items'.// التكرار عبر 'items'. // 'it' من النوع vector<int>::iterator for ( auto it = items . begin (), end = items . end (); it != end ; ++ it ) { // وطباعة قيمة 'items' للفهرس الحالي. std :: print ( "{}" , * it ); }// باستخدام حلقات foreach (المضافة في C++11)، // يمكن فعل الشيء نفسه دون استخدام أي مُكرِّرات صريحة: for ( int x : items ) { // طباعة قيمة كل عنصر 'x' من 'items'. std :: print ( "{}" , x ); }// كلا حلقتي التكرار تطبعان "529". }أنواع المُكرِّرات منفصلة عن أنواع الحاويات التي تُستخدم معها، على الرغم من أنهما يُستخدمان غالبًا معًا. يعتمد تصنيف المُكرِّر (وبالتالي العمليات المُعرَّفة له) عادةً على نوع الحاوية، حيث تُوفِّر المصفوفات أو المتجهات، على سبيل المثال، مُكرِّرات وصول عشوائي، بينما تُوفِّر المجموعات (التي تستخدم بنية مرتبطة كتنفيذ) مُكرِّرات ثنائية الاتجاه فقط. يمكن أن يكون لنوع حاوية واحد أكثر من نوع مُكرِّر مرتبط به؛ على سبيل المثال، std::vector<T>يسمح نوع الحاوية بالتنقل إما باستخدام مؤشرات (أولية) إلى عناصره (من النوع T*)، أو قيم من نوع خاص std::vector<T>::iterator، وهناك نوع آخر مُخصَّص لـ "المُكرِّرات العكسية"، التي تُعرَّف عملياتها بطريقة تجعل الخوارزمية التي تُنفِّذ تنقلًا عاديًا (أماميًا) تُنفِّذ التنقل بترتيب عكسي عند استدعائها باستخدام مُكرِّرات عكسية. تُوفِّر معظم الحاويات أيضًا const_iteratorنوعًا منفصلًا، لا تُعرَّف له عمدًا العمليات التي تسمح بتغيير القيم المُشار إليها.
const_iteratorيمكن إجراء اجتياز بسيط لكائن حاوية أو نطاق من عناصره (بما في ذلك تعديل تلك العناصر ما لم يتم استخدام `a` ) باستخدام المُكرِّرات فقط. ولكن قد توفر أنواع الحاويات أيضًا طرقًا مثل `return` insertأو ` erasereturn` التي تُعدِّل بنية الحاوية نفسها؛ هذه طرق خاصة بفئة الحاوية، ولكنها تتطلب بالإضافة إلى ذلك قيمة مُكرِّر واحدة أو أكثر لتحديد العملية المطلوبة. على الرغم من أنه من الممكن أن تشير مُكرِّرات متعددة إلى نفس الحاوية في وقت واحد، إلا أن عمليات تعديل البنية قد تُبطل بعض قيم المُكرِّرات (يُحدد المعيار لكل حالة ما إذا كان هذا ممكنًا أم لا)؛ استخدام مُكرِّر مُبطل يُعد خطأً سيؤدي إلى سلوك غير مُعرَّف ، ولا يلزم أن يُشير نظام وقت التشغيل إلى مثل هذه الأخطاء.
كما يدعم C++ التكرار الضمني جزئيًا من خلال استخدام قوالب الدوال القياسية، std::for_each()مثل std::copy() و std::accumulate().
عند استخدامها، يجب تهيئتها باستخدام مُكرِّرات موجودة، عادةً `x` beginو`y` end، والتي تُحدد النطاق الذي يتم التكرار عليه. ولكن لا يتم عرض أي كائن مُكرِّر صريح لاحقًا أثناء تقدم عملية التكرار. يُوضح هذا المثال استخدام `x` for_each.
// أي نوع حاوية قياسي لعناصر ItemType. ContainerType < ItemType > c ;// دالة تعالج كل عنصر من عناصر المجموعة. void processItem ( const ItemType & i ) { std :: println ( "{}" , i ); }// حلقة تكرار for-each. std :: for_each ( c.begin ( ), c.end ( ), processItem ) ; // باستخدام std::ranges: std :: ranges :: for_each ( c , processItem );ويمكن تحقيق نفس النتيجة باستخدام std::copy، مع تمرير std::ostream_iteratorقيمة كمكرر ثالث:
باستخدام std :: cout ؛ باستخدام std :: ostream_iterator ؛std :: copy ( c.begin ( ) , c.end ( ), ostream_iterator <ItemType> ( cout , " \n " ) ) ; // باستخدام std::ranges: std :: ranges :: copy ( c , ostream_iterator <ItemType> ( cout , " \ n " ) );منذ إصدار C++11 ، أصبح بالإمكان استخدام صيغة دالة لامدا لتحديد العملية المراد تكرارها مباشرةً، مما يُغني عن الحاجة إلى تعريف دالة مُسماة. إليك مثال على تكرار حلقة for-each باستخدام دالة لامدا:
ContainerType < ItemType > c ; // أي نوع حاوية قياسي لعناصر ItemType.// حلقة تكرارية for-each مع دالة لامدا. std :: for_each ( c.begin ( ), c.end ( ) , [ ] ( const ItemType & i ) -> void { std :: println ( "{}" , i ); });// باستخدام std::ranges: std :: ranges :: for_each ( c , []( const ItemType & i ) -> void { std :: println ( "{}" , i ); });يمكن تطبيق صيغة Java الخاصة بالمكررات ( Iterator<T>, vs T::iterator) في لغة C++ بالطريقة التالية:
استيراد std ؛namespace { // مفهوم مساعد: إذا كان يحتوي على مُكرِّر template < typename T > concept Has_iterator = requires { typename T :: iterator }; }template < typename Iterable > requires Has_iterator < Iterable > using Iterator = typename Iterable :: iterator ;// يمكن الآن استدعاؤها على النحو التالي:template < typename T > using Vector = std :: vector < T > ;int main () { Vector < int > v { 1 , 2 , 3 , 4 , 5 }; for ( Iterator < Vector < int >> it = v . begin (); it != v . end (); ++ it ) { std :: println ( "{}" , * it ); } }جافا
تتيح هذه الواجهة، التي طُرحت في إصدار Java JDK 1.2، java.util.Iteratorإمكانية تكرار فئات الحاويات. Iteratorتوفر كل فئة طريقةً next()ودالةً hasNext()، [ 20 ] : 294-295 ، وقد تدعم اختياريًا طريقةً أخرى، remove()[ 20 ] : 262، 266. تُنشأ المُكرِّرات بواسطة فئة الحاوية المُقابلة، عادةً بواسطة دالة تُسمى iterator(). [ 21 ] [ 20 ] : 99 [ 20 ] : 217
تُحرك هذه next()الطريقة المؤشر وتُعيد القيمة التي يُشير إليها. يتم الحصول على العنصر الأول عند أول استدعاء لها next(). [ 20 ] : 294-295. لتحديد متى تمت زيارة جميع العناصر في الحاوية، hasNext()تُستخدم طريقة الاختبار. [ 20 ] : 262. يُوضح المثال التالي استخدامًا بسيطًا للمُكررات:
استيراد java.util.Iterator ؛Iterator iter = list.iterator ( ) ; Iterator <MyType> iter = list.iterator ( ); // Iterator iter = list.iterator( ) ; قبل J2SE 5.0 while ( iter.hasNext ( ) ) { System.out.print ( iter.next ( ) ) ; if ( iter.hasNext ( ) ) { System.out.print ( " , " ) ; } }ولإظهار أنه hasNext()يمكن استدعاء ذلك بشكل متكرر، نستخدمه لإدراج الفواصل بين العناصر ولكن ليس بعد العنصر الأخير.
لا يفصل هذا الأسلوب عملية التقدم عن الوصول الفعلي إلى البيانات بشكل صحيح. إذا كان يجب استخدام عنصر البيانات أكثر من مرة لكل عملية تقدم، فيجب تخزينه في متغير مؤقت . عند الحاجة إلى التقدم دون الوصول إلى البيانات (أي لتجاوز عنصر بيانات معين)، يتم الوصول إلى البيانات على أي حال، مع تجاهل القيمة المُعادة في هذه الحالة.
بالنسبة لأنواع المجموعات التي تدعم هذه الخاصية، remove()تقوم دالة المُكرِّر بإزالة العنصر الذي تمت زيارته مؤخرًا من الحاوية مع الحفاظ على إمكانية استخدام المُكرِّر. يؤدي إضافة أو إزالة عناصر عن طريق استدعاء دوال الحاوية (حتى من نفس سلسلة العمليات ) إلى جعل المُكرِّر غير قابل للاستخدام. محاولة الحصول على العنصر التالي تُطلق استثناءً. كما يُطلق استثناء أيضًا في حال عدم وجود عناصر متبقية (إذا hasNext()كانت الدالة قد أعادت القيمة false سابقًا).
بالإضافة إلى ذلك، java.util.Listهناك java.util.ListIteratorواجهة برمجة تطبيقات مماثلة تسمح بالتكرار الأمامي والخلفي، وتوفر فهرسها الحالي في القائمة وتسمح بتعيين عنصر القائمة في موضعه.
قدّم إصدار J2SE 5.0 من Java Iterableواجهةً لدعم حلقة for( foreach ) مُحسّنة للتكرار على المجموعات والمصفوفات. Iterableتُعرّف هذه iterator()الواجهة الطريقة التي تُعيد قيمةً Iterator. [ 20 ] : 266 باستخدام الحلقة المُحسّنة for، يُمكن إعادة كتابة المثال السابق على النحو التالي:
for ( MyType obj : list ) { System.out.print ( obj ) ; }تستخدم بعض الحاويات أيضًا الفئة الأقدم (منذ الإصدار 1.0) Enumeration. توفر هذه الفئة طرقًا hasMoreElements()، nextElement()ولكنها لا تحتوي على طرق لتعديل الحاوية.
سكالا
في لغة سكالا ، تتمتع المُكرِّرات بمجموعة غنية من الدوال المشابهة للمجموعات، ويمكن استخدامها مباشرةً في حلقات التكرار. في الواقع، ترث كل من المُكرِّرات والمجموعات سمة أساسية مشتركة scala.collection.TraversableOnce. مع ذلك، ونظرًا لغنى مكتبة المجموعات في سكالا بالدوال المتاحة، مثل map`require` collectو` filterrequire` وغيرها، فغالبًا لا يكون من الضروري التعامل مع المُكرِّرات مباشرةً عند البرمجة بلغة سكالا.
يمكن تحويل مُكرِّرات ومجموعات Java تلقائيًا إلى مُكرِّرات ومجموعات Scala، على التوالي، ببساطة عن طريق إضافة سطر واحد.
import scala.collection.JavaConversions._إلى الملف. JavaConversionsيوفر الكائن تحويلات ضمنية للقيام بذلك. التحويلات الضمنية هي إحدى ميزات لغة سكالا: وهي عبارة عن دوال، عندما تكون مرئية في النطاق الحالي، تُدرج تلقائيًا استدعاءات لنفسها في التعبيرات ذات الصلة في المكان المناسب لجعلها قابلة للتحقق من النوع عندما لا تكون كذلك في الأحوال العادية.
MATLAB
يدعم MATLAB التكرار الضمني الخارجي والداخلي باستخدام المصفوفات الأصلية أو cellالمصفوفات. في حالة التكرار الخارجي، حيث تقع مسؤولية التقدم في عملية التصفح وطلب العناصر التالية على عاتق المستخدم، يمكن تعريف مجموعة من العناصر ضمن بنية تخزين مصفوفة، ثم التصفح بين هذه العناصر باستخدام forبنية الحلقة. على سبيل المثال،
% تعريف مصفوفة من الأعداد الصحيحة myArray = [ 1 , 3 , 5 , 7 , 11 , 13 ];for n = myArray % ... do something with n disp ( n ) % Echo in the Command Window endيجتاز مصفوفة من الأعداد الصحيحة باستخدام الكلمة forالمفتاحية.
في حالة التكرار الداخلي، حيث يُمكن للمستخدم تحديد عملية للمُكرِّر لتنفيذها على كل عنصر من عناصر المجموعة، يتم تحميل العديد من المعاملات ووظائف MATLAB المُدمجة لتنفيذها على كل عنصر من عناصر المصفوفة وإرجاع مصفوفة إخراج مُطابقة ضمنيًا. علاوة على ذلك، يُمكن الاستفادة من الدالتين arrayfun`and` cellfunلتنفيذ عمليات مُخصصة أو مُعرَّفة من قِبل المستخدم على المصفوفات الأصلية والمصفوفات cellالمُعرَّفة على التوالي. على سبيل المثال،
دالة simpleFun % تعريف مصفوفة من الأعداد الصحيحة myArray = [ 1 , 3 , 5 , 7 , 11 , 13 ];% قم بتنفيذ عملية مخصصة على كل عنصر myNewArray = arrayfun (@( a ) myCustomFun ( a ), myArray );% اطبع المصفوفة الناتجة في نافذة الأوامر myNewArrayدالة outScalar = myCustomFun ( inScalar ) % ببساطة اضرب في 2 outScalar = 2 * inScalar ;تُعرّف دالة أساسية simpleFunتقوم ضمنيًا بتطبيق دالة فرعية مخصصة myCustomFunعلى كل عنصر من عناصر المصفوفة باستخدام دالة مدمجة arrayfun.
بدلاً من ذلك، قد يكون من المستحسن تجريد آليات حاوية تخزين المصفوفة عن المستخدم من خلال تعريف تطبيق MATLAB مخصص كائني التوجه لنمط المُكرِّر. يُوضَّح هذا التطبيق، الذي يدعم التكرار الخارجي، في عنصر " نمط التصميم: المُكرِّر (السلوكي)" في MATLAB Central File Exchange . كُتِبَ هذا التطبيق باستخدام صيغة تعريف الفئة الجديدة المُقدَّمة مع إصدار برنامج MATLAB 7.6 (R2008a)، ويتميز cellبتحقيق مصفوفة أحادية البُعد لنوع بيانات القائمة المجردة (ADT) كآلية لتخزين مجموعة غير متجانسة (من حيث نوع البيانات) من العناصر. يوفر هذا التطبيق وظائف اجتياز القائمة الأمامي الصريح باستخدام طرق `include` hasNext()و` include` next()و` reset()include` للاستخدام في whileحلقة `include`.
PHP

foreachتم تقديم حلقة التكرار في PHP في الإصدار 4.0، وأصبحت متوافقة مع الكائنات كقيم في الإصدار التجريبي 4.0 بيتا 4. [ 22 ] ومع ذلك، أُضيف دعم المُكرِّرات في PHP 5 من خلال تقديم الواجهة الداخلية [ 23 ]Traversable . [ 24 ] الواجهتان الرئيسيتان للتنفيذ في نصوص PHP التي تُمكِّن من تكرار الكائنات عبر foreachحلقة التكرار هما `input` Iteratorو`input` IteratorAggregate. لا تتطلب الأخيرة من الفئة المُنفِّذة تعريف جميع الطرق المطلوبة، بل تُنفِّذ طريقة وصولgetIterator (`accessor` ) تُعيد نسخة من `input` Traversable. توفر مكتبة PHP القياسية عدة فئات للعمل مع المُكرِّرات الخاصة. [ 25 ] يدعم PHP أيضًا المُولِّدات منذ الإصدار 5.5. [ 26 ]
أبسط طريقة للتنفيذ هي عن طريق تغليف مصفوفة، وهذا يمكن أن يكون مفيدًا للتلميح إلى النوع وإخفاء المعلومات .
namespace Wikipedia\Iterator ;الفئة النهائية ArrayIterator تمتد من \Iterator { مصفوفة خاصة $array ;public function __construct ( array $array ) { $this -> array = $array ; }public function rewind () : void { echo 'rewinding' , PHP_EOL ; reset ( $this- > array ); }public function current () { $value = current ( $this- > array ); echo "current: { $value } " , PHP_EOL ; return $value ; }public function key () { $key = key ( $this -> array ); echo "key: { $key } " , PHP_EOL ; return $key ; }public function next () { $value = next ( $this- > array ); echo "next: { $value } " , PHP_EOL ; return $value ; }public function valid () : bool { $valid = $this- > current () !== false ; echo 'valid: ' , ( $valid ? 'true' : 'false' ), PHP_EOL ; return $valid ; } }تُستخدم جميع طرق فئة المثال أثناء تنفيذ حلقة foreach كاملة foreach ($iterator as $key => $current) {}. تُنفذ طرق المُكرِّر بالترتيب التالي:
$iterator->rewind()يضمن ذلك أن يبدأ الهيكل الداخلي من البداية.$iterator->valid()في هذا المثال، تكون النتيجة صحيحة .$iterator->current()يتم تخزين القيمة المُعادة في$value.$iterator->key()يتم تخزين القيمة المُعادة في$key.$iterator->next()ينتقل إلى العنصر التالي في البنية الداخلية.$iterator->valid()تُرجع الدالة القيمة false ويتم إيقاف الحلقة.
يوضح المثال التالي فئة PHP تُنفذ الواجهة Traversable، والتي يمكن تغليفها في IteratorIteratorفئة أخرى لمعالجة البيانات قبل إعادتها إلى foreachالحلقة. يتيح هذا الاستخدام، بالإضافة إلى MYSQLI_USE_RESULTالثابت، لبرامج PHP تكرار مجموعات النتائج التي تحتوي على مليارات الصفوف مع استهلاك ضئيل جدًا للذاكرة. هذه الميزات ليست حصرية لـ PHP ولا لتطبيقات فئات MySQL الخاصة بها (على سبيل المثال، PDOStatementتُنفذ الفئة Traversableالواجهة أيضًا).
mysqli_report ( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT ); $mysqli = new \mysqli ( 'host.example.com' , 'username' , 'password' , 'database_name' );// تُنفّذ فئة `mysqli_result` المُعادة من استدعاء الدالة واجهة Traversable الداخلية. foreach ( $mysqli -> query ( 'SELECT `a`, `b`, `c` FROM `table`' , MYSQLI_USE_RESULT ) as $row ) { // تنفيذ الإجراء على الصف المُعاد، وهو عبارة عن مصفوفة ترابطية. }بايثون
تُعدّ المُكرِّرات في بايثون جزءًا أساسيًا من اللغة، وفي كثير من الأحيان لا تُرى لأنها تُستخدم ضمنيًا في عبارة for( foreach )، وفي تراكيب القوائم ، وفي تعابير المُولِّدات . تدعم جميع أنواع المجموعات القياسية المُضمَّنة في بايثون التكرار، بالإضافة إلى العديد من الفئات التي تُشكِّل جزءًا من المكتبة القياسية. يُوضِّح المثال التالي التكرار الضمني النموذجي على مُتتالية:
for value in sequence : print ( value )يمكن أيضًا تكرار قواميس بايثون (وهي شكل من أشكال المصفوفات الترابطيةitems() ) بشكل مباشر، عند إرجاع مفاتيح القاموس؛ أو يمكن تكرار طريقة القاموس حيث تُنتج أزواج المفاتيح والقيم المقابلة كصف:
for key in dictionary : value = dictionary [ key ] print ( key , value )for key , value in dictionary.items ( ) : print ( key , value )مع ذلك، يمكن استخدام المُكرِّرات وتحديدها بشكل صريح. لأي نوع أو فئة من أنواع التسلسلات القابلة للتكرار، iter()تُستخدم الدالة المُضمَّنة لإنشاء كائن مُكرِّر. يمكن بعد ذلك تكرار كائن المُكرِّر باستخدام next()الدالة، التي تستخدم __next__()داخليًا الطريقة التي تُعيد العنصر التالي في الحاوية. (ينطبق البيان السابق على بايثون 3.x. في بايثون 2.x، next()تكون الطريقة مُكافئة). StopIterationسيتم طرح استثناء عند عدم وجود عناصر متبقية. يُظهر المثال التالي تكرارًا مُكافئًا على تسلسل باستخدام مُكرِّرات صريحة:
من typing استورد Iteratorsequence : list [ int ] = [ 1 , 2 , 3 , 4 ] it : Iterator [ int ] = iter ( sequence ) while True : try : value = it.next ( ) # في بايثون 2.x value = next ( it ) # في بايثون 3.x except StopIteration : break print ( value )يمكن لأي فئة معرفة من قبل المستخدم أن تدعم التكرار القياسي (سواء كان ضمنيًا أو صريحًا) عن طريق تعريف __iter__()دالة تُرجع كائنًا مُكرِّرًا. ثم يحتاج الكائن المُكرِّر إلى تعريف __next__()دالة تُرجع العنصر التالي.
راكو
تُعدّ المُكرِّرات في لغة Raku جزءًا أساسيًا منها، مع أن المستخدمين عادةً لا يحتاجون إلى الاهتمام بها. يتم إخفاء استخدامها خلف واجهات برمجة تطبيقات التكرار، مثل عبارة `return` for، mapو` grepreturn`، وفهرسة القوائم باستخدام `return` .[$idx]، وما إلى ذلك.
يوضح المثال التالي عملية التكرار الضمني النموذجية على مجموعة من القيم:
my @values = 1 , 2 , 3 ; for @values -> $value { say $value } المخرجات: 1 2 3يمكن أيضًا تكرار عناصر التجزئة في Raku مباشرةً، مما ينتج عنه Pairكائنات مفتاح-قيمة. kvيمكن استدعاء الدالة على التجزئة للتكرار على المفتاح والقيم؛ keysوالدالة للتكرار على مفاتيح التجزئة؛ والدالة valuesللتكرار على قيم التجزئة.
my %word-to-number = 'one' => 1 , 'two' => 2 , 'three' => 3 ; for %word-to-number -> $pair { say $pair ; } الناتج: ثلاثة => 3 واحد => 1 اثنان => 2for %word-to-number . kv -> $key , $value { say "$key: $value" } الناتج: ثلاثة: 3 واحد: 1 اثنان: 2for %word-to-number . keys -> $key { say "$key => " ~ %word-to-number { $key }; } الناتج: ثلاثة => 3 واحد => 1 اثنان => 2مع ذلك، يمكن استخدام المُكرِّرات وتحديدها بشكل صريح. بالنسبة لأي نوع قابل للتكرار، توجد عدة طرق تتحكم في جوانب مختلفة من عملية التكرار. على سبيل المثال، iteratorمن المفترض أن تُعيد الطريقة Iteratorكائنًا، ومن pull-oneالمفترض أن تُنتج الطريقة التالية وتُعيدها إن أمكن، أو تُعيد القيمة المرجعيةIterationEnd إذا لم يكن بالإمكان إنتاج المزيد من القيم. يُوضح المثال التالي تكرارًا مُكافئًا على مجموعة باستخدام مُكرِّرات صريحة:
my @values = 1 , 2 , 3 ; my $it := @values.iterator ; # الحصول على مُكرِّر @valuesloop { my $value := $it . pull-one ; # الحصول على القيمة التالية للتكرار أخيرًا if $value =:= IterationEnd ; # التوقف إذا وصلنا إلى نهاية التكرار say $value ; } المخرجات: 1 2 3تُشكّل جميع الأنواع القابلة للتكرار في راكو Iterableالدور، أو Iteratorالدور، أو كليهما. الدور الأول Iterableبسيط للغاية، ولا يتطلب سوى iteratorتنفيذه بواسطة الفئة المُكوِّنة. أما الدور الثاني Iteratorفهو أكثر تعقيدًا، ويُوفّر سلسلة من الطرق مثل pull-one، مما يسمح بعملية تكرار أدق في سياقات متعددة، كإضافة العناصر أو حذفها، أو تخطيها للوصول إلى عناصر أخرى. بالتالي، يُمكن لأي فئة مُعرَّفة من قِبل المستخدم دعم التكرار القياسي من خلال تكوين هذه الأدوار وتنفيذ طرق iteratorو/أو pull-one.
يمثل هذا DNAالصنف شريط الحمض النووي (DNA) وينفذه iteratorمن خلال تكوين Iterableالدور. يتم تقسيم شريط الحمض النووي إلى مجموعة من ثلاثيات النوكليوتيدات عند تكراره على:
مجموعة فرعية Strand من Str حيث { . match ( /^^ <[ACGT]>+ $$/ ) و . chars %% 3 }; فئة DNA تقوم بـ Iterable { لديها $.chain ; طريقة new ( Strand:D $chain ) { self . bless: : $chain } method iterator ( DNA:D: ){ $.chain . comb . rotor ( 3 ). iterator } }; للحمض النووي . جديد ( 'جاتاكاتا' ) { . يقول } المخرجات: (GAT) (TAC) (ATA)قل DNA.new ( ' GATTACATA' ). map ( *. join ) .join ( '-' ); # الناتج: # GAT-TAC-ATAيشمل هذا Repeaterالصنف كلا Iterableالدورين Iterator:
class Repeater does Iterable does Iterator { has Any $.item is required ; has Int $.times is required ; has Int $!count = 1 ; multi method new ( $item , $times ) { self . bless: : $item , : $times ; } دالة iterator { self } دالة pull-one (--> Mu ){ إذا كان $!count <= $!times { $!count += 1 ; return $!item } وإلا { أعد نهاية التكرار } } } for Repeater.new ( "Hello " , 3 ) { . يقول } المخرجات: مرحباً مرحباً مرحباًروبي
تُنفّذ لغة روبي المُكرِّرات بطريقة مختلفة تمامًا؛ إذ تتم جميع عمليات التكرار عن طريق تمرير دوال رد نداء إلى دوال الحاوية. وبهذه الطريقة، لا تُنفّذ روبي التكرار الأساسي فحسب، بل تُنفّذ أيضًا أنماطًا متعددة من التكرار مثل تعيين الدوال، والمرشحات، والاختزال. كما تدعم روبي صيغة بديلة لطريقة التكرار الأساسية each، والأمثلة الثلاثة التالية متكافئة:
( 0 ... 42 ) . كل حلقة كرر | ن | ضع ن نهاية...و...
for n in 0 ... 42 puts n endأو حتى أقصر
٤٢. مرات do | n | puts n endيمكن لـ Ruby أيضًا التكرار على القوائم الثابتة باستخدام Enumerators إما عن طريق استدعاء طريقتها #nextأو القيام بـ for each عليها، كما هو موضح أعلاه.
الصدأ
تستخدم لغة Rust المُكرِّرات الخارجية في جميع أنحاء المكتبة القياسية، بما في ذلك في forحلقة التكرار الخاصة بها، والتي تستدعي ضمنيًا دالة المُكرِّر حتى يتم استهلاكها. على سبيل المثال، تقوم next()أبسط حلقة تكرار بالتكرار على نوع معين:forRange
for i in 0 .. 42 { println! ( "{}" , i ); } // يطبع الأرقام من 0 إلى 41على وجه التحديد، forستستدعي الحلقة دالة القيمة into_iter()، التي تُعيد مُكرِّرًا يُمرِّر بدوره العناصر إلى الحلقة. forوتستمر الحلقة (أو أي دالة تستهلك المُكرِّر) حتى next()تُعيد الدالة Noneقيمة (تُعيد التكرارات التي تُنتج عناصر Some(T)قيمةً، حيث Tيُمثِّل نوع العنصر).
تُطبّق جميع المجموعات التي توفرها المكتبة القياسية هذه IntoIteratorالسمة (أي أنها تُعرّف into_iter()الدالة). وتُطبّق المُكرِّرات نفسها هذه Iteratorالسمة، الأمر الذي يتطلب تعريف next()الدالة. علاوة على ذلك، يُزوَّد أي نوع يُطبّق هذه السمة Iteratorتلقائيًا بتنفيذ IntoIteratorيُعيد نفسه.
تدعم المكررات محولات متنوعة ( ،،،، map()إلخ filter(). ) كطرق يتم توفيرها تلقائيًا بواسطة السمة.skip()take()Iterator
يمكن للمستخدمين إنشاء مُكرِّرات مُخصَّصة عن طريق إنشاء نوع يُطبِّق Iteratorالسمة. يمكن للمجموعات المُخصَّصة تطبيق IntoIteratorالسمة وإرجاع نوع مُكرِّر مُرتبط بعناصرها، مما يُتيح استخدامها مُباشرةً في forالحلقات. فيما يلي، Fibonacciيُطبِّق النوع مُكرِّرًا مُخصَّصًا غير محدود:
struct Fibonacci ( u64 , u64 );impl Fibonacci { pub fn new () -> Self { Self ( 0 , 1 ) } }impl Iterator for Fibonacci { type Item = u64 ;fn next ( & mut self ) - > Option < Self :: Item > { let next = self.0 ; self.0 = self.1 ; self.1 = self.0 + next ;بعض ( التالي ) } }fn main () { let fib = Fibonacci :: new (); for n in fib . skip ( 1 ). step_by ( 2 ). take ( 4 ) { println! ( "{n}" ); } // يطبع 1، 2، 5، و13 }![]()
انظر أيضاً
- المكرر
- نمط التصميم (علوم الحاسوب) – قالب حل قابل لإعادة الاستخدام لسلوك برمجي شائع الاستخدام. صفحات تعرض أوصافًا مختصرة لأهداف إعادة التوجيه
- المولد (برمجة الحاسوب) - روتين يقوم بتوليد سلسلة من القيم
- نطاق (علوم الحاسوب)
- نمط الزائر – نمط تصميم البرمجيات
مراجع
- ↑ جاتكومب، جوشوا (16 يونيو 2005). "فهم واستخدام المُكرِّرات" . Perl.com . تاريخ الاسترجاع: 8 أغسطس 2012.
عادةً ما يأخذ المُكرِّر المُعرَّف من قِبل المستخدم شكل مرجع برمجي، يقوم عند تنفيذه بحساب العنصر التالي في القائمة وإعادته. وعندما يصل المُكرِّر إلى نهاية القائمة، يُعيد قيمة مُتفق عليها.
- 1 2 وات، ستيفن م. (16 سبتمبر 2006). "تقنية للتكرار العام وتحسينها" (ملف PDF) . جامعة ويسترن أونتاريو، قسم علوم الحاسوب . تاريخ الاسترجاع: 8 أغسطس 2012.
تم تقديم المُكرِّرات كبنى تسمح بالتكرار على هياكل البيانات المجردة دون الكشف عن تمثيلها الداخلي.
- ↑ أليكس ألين. "مكررات STL" . Cprogramming.com - مرجعك للغة C و C++ . تاريخ الاسترجاع: 8 أغسطس 2012.
يمكنك اعتبار المكرر بمثابة مؤشر إلى عنصر ضمن حاوية أكبر من العناصر.
- ↑ ليسكوف، ب .؛ سنايدر، أ.؛ أتكينسون، ر.؛ شافرت، س. (أغسطس 1977). "آليات التجريد في لغة CLU". مجلة اتصالات ACM . 20 (8): 564-576 . CiteSeerX 10.1.1.112.656 . doi : 10.1145/359763.359789 . S2CID 17343380 .
- ١ ٢ "الفرق بين المُكرِّر الخارجي والمُكرِّر الداخلي" . CareerRide.COM. ٢٠٠٩-٠٤-٠٣. مؤرشف من الأصل في ٢٠١٢-٠٩-١٩ . تم الاطلاع عليه في ٢٠١٢-٠٨-٠٨ .
يُنفَّذ المُكرِّر الداخلي بواسطة الدوال الأعضاء للفئة التي تحتوي على منطق التكرار. أما المُكرِّر الخارجي فيُنفَّذ بواسطة فئة منفصلة يمكن إلحاقها بالكائن الذي يحتوي على منطق التكرار. وتكمن ميزة المُكرِّر الخارجي في إمكانية تفعيل العديد من المُكرِّرات في وقت واحد على نفس الكائن الموجود.
{{cite web}}: CS1 maint: bot: حالة عنوان URL الأصلي غير معروفة ( رابط ) - ↑ وات، ستيفن م. " تقنية للتكرار العام وتحسينه" . جامعة ويسترن أونتاريو، قسم علوم الحاسوب. مؤرشف من الأصل بتاريخ 6 أغسطس 2012. تم الاطلاع عليه بتاريخ 8 أغسطس 2012.
يستخدم بعض المؤلفين مصطلح "المكرر"، بينما يستخدم آخرون مصطلح "المولد". ويُجري البعض تمييزات دقيقة بينهما.
{{cite web}}: CS1 maint: bot: حالة عنوان URL الأصلي غير معروفة ( رابط ) - 1 2 فريمان، إريك؛ فريمان، إليزابيث؛ كاثي، سييرا؛ بيرت، بيتس (2004). هندريكسون، مايك؛ لوكيدس، مايك (محرران). أنماط التصميم من البداية (غلاف ورقي) . المجلد 1. أورايلي. ص 338. ISBN 978-0-596-00712-6تم الاطلاع عليه بتاريخ 9 أغسطس 2012 .
- ↑ "مسرد المصطلحات - وثائق بايثون 3.8.4" . تم الاطلاع عليه بتاريخ 15 يوليو 2020 .
- ↑ فيسيرينا، إيفان (2006-02-01). "الفهرس مقابل المُكرِّر" . بايتس. مؤرشف من الأصل في 2012-08-09 . تم الاسترجاع في 2012-08-08 .
لا يُمكن استخدام الفهرس إلا للحاويات التي تدعم (بكفاءة) الوصول العشوائي (أي الوصول المباشر إلى عنصر في موضع مُحدد). المُكرِّر مفهوم أعمّ. تُتيح المُكرِّرات اجتيازًا فعالًا للقوائم المرتبطة والملفات وعدد من هياكل البيانات الأخرى. وغالبًا ما تُؤدي إلى توليد شفرة برمجية أكثر كفاءة.
{{cite web}}: CS1 maint: bot: حالة عنوان URL الأصلي غير معروفة ( رابط ) - ↑ كيفن واترسون. "مكررات لغة C++: فئات المكررات" (بالألمانية). cppreference.com . تاريخ الاسترجاع: 9 أغسطس 2012 .
- ↑ كيفن واترسون. "المكررات: مفاهيم" . sgi . تم الاسترجاع في 2012-08-09 .
- ↑ "DoubleEndedIterator in std::iter - Rust" . doc.rust-lang.org . تم الاطلاع عليه بتاريخ 11 مايو 2025 .
- ↑ لارسمانز (2011-03-06). "أنواع المُكرِّرات: مُكرِّر الإخراج مقابل مُكرِّر الإدخال مقابل مُكرِّر الوصول الأمامي مقابل مُكرِّر الوصول العشوائي" . موقع ستاك أوفر فلو. مؤرشف من الأصل بتاريخ 2012-08-08 . تم الاطلاع عليه بتاريخ 2012-08-09 .
{{cite web}}: CS1 maint: bot: حالة عنوان URL الأصلي غير معروفة ( رابط ) - ↑ كيفن واترسون. "مقدمة إلى SPL: مقدمة إلى مكتبة PHP القياسية (SPL)" . PHPRO.ORG . تم الاطلاع عليه بتاريخ 9 أغسطس 2012 .
- ↑ كولير، أندرو. "المكررات في لغة R" . مؤرشف من الأصل في 18 أكتوبر 2018. تم الاسترجاع في 16 نوفمبر 2013 .
- ↑ "فئة قالب المجموعة غير المرتبة المتزامنة" . لبنات بناء سلاسل العمليات من إنتل للمصادر المفتوحة. مؤرشف من الأصل في 1 مايو 2015. تم الاسترجاع في 9 أغسطس 2012.
• ينتمي نوعا المُكرِّر iterator و const_iterator إلى فئة المُكرِّر الأمامي
. - 1 2 3 4 5 البحاري، يوسف (2022). C#10 باختصار . أورايلي. رقم ISBN 978-1-098-12195-2.
- 1 2 3 4 5 سكيت، جون (23 مارس 2019). لغة سي شارب بتفصيل . مانينغ. ISBN 978-1617294532.
- 1 2 3 4 5 برايس، مارك ج. سي شارب 8.0 و.نت كور 3.0 - تطوير تطبيقات حديثة متعددة المنصات: بناء تطبيقات باستخدام سي شارب، و.نت كور، وإنتيتي فريم وورك كور، وإيه إس بي.نت كور، وإم إل.نت باستخدام فيجوال ستوديو كود . باكْت. رقم ISBN 978-1-098-12195-2.
- 1 2 3 4 5 6 7 بلوخ، جوشوا (2018). "جافا الفعّالة: دليل لغة البرمجة" ( الطبعة الثالثة). أديسون-ويسلي. ISBN 978-0134685991.
- ↑ "java.util: Interface Iterator<E>: Method Summary" . Oracle . تم الاسترجاع في 2012-08-08 .
- ↑ "سجل تغييرات PHP 4" . مجموعة PHP. 2000-02-20 . تم الاطلاع عليه بتاريخ 2015-10-13 .
- ↑ يشير مصطلح "داخلي" إلى حقيقة أنه لا يمكن تنفيذ الواجهة في نصوص PHP، بل فقط في مصدر لغة C (لغة البرمجة) .
- ↑ "واجهة Traversable" . مجموعة PHP . تم الاطلاع عليه بتاريخ 13-10-2015 .
- ↑ "المكررات" . مجموعة PHP . تم الاسترجاع في 13-10-2015 .
- ↑ "سجل تغييرات PHP 5" . مجموعة PHP. 2013-06-20 . تم الاطلاع عليه بتاريخ 2015-10-13 .
روابط خارجية
- شرح مُكرِّرات جافا، والعناصر القابلة للتكرار، وقوائم التكرار
- واجهة .NET
- مقال بعنوان " فهم واستخدام المُكرِّرات " بقلم جوشوا جاتكومب
- مقال بعنوان " تقنية للتكرار العام وتحسينه" مؤرشف بتاريخ 9 يوليو 2020 على موقع Wayback Machine (217 كيلوبايت) بقلم ستيفن إم. وات
- المكررات
- مكتبة Boost C++ للتكرار
- واجهة جافا
- PHP: تكرار الكائنات
- مكررات STL
- ما هي المُكرِّرات؟ - وصف مرجعي
- التكرار في البرمجة
- كائن (علوم الحاسوب)
- أنواع البيانات المجردة
