بعد أسابيع من الترقب، تجتمع أنت وأصدقاؤك لأول لعبة لكم من Dungeons & Dragons (D&D). ولأن هذه أول جلسة في اللعبة، فعلى كل لاعب أن يُنشئ شخصية يلعب بها. تُحدَّد قدرات الشخصية برمي نرد ذي ستة أوجه، ولكن أين النرد فعلًا؟ وترتجف من الصدمة حين تدرك أن أصدقاءك ينتظرون منك أنت أن تُحضر النرد، فقد كانت فكرتك أنت أن تلعبوا D&D! وحين تصاب بالذعر، تدرك أنك نسيت إحضار النرد، ما يعني ألا لعبة D&D. ولأنك تملك بعض مهارات البرمجة الأساسية، تجد حلًا سريعًا: ستكتب برنامجًا يحاكي رمي النرد.
في لعبة Dungeons & Dragons، يبدأ كل لاعب بتوليد شخصية يمكنه اللعب بها. وللشخصية، من بين أمور أخرى، ست قدرات: القوة والرشاقة والبنية والذكاء والحكمة والكاريزما. وهذه القدرات الست لها درجات تُحدَّد عشوائيًا. وتفعل ذلك برمي أربعة أحجار نرد ذات 6 أوجه وتسجيل مجموع أكبر ثلاثة أحجار. وتفعل ذلك ست مرات، مرة لكل قدرة.
نقاط الصحة الأولية لشخصيتك تساوي 10 + معدِّل بنية شخصيتك. وتجد معدِّل بنية شخصيتك بطرح 10 من بنية شخصيتك، ثم القسمة على 2 والتقريب إلى أسفل.
اكتب مولِّد شخصيات عشوائيًا يتبع القواعد أعلاه.
على سبيل المثال، قد تبدو الرميات الست لأربعة أحجار النرد كما يلي:
ولأن البنية تساوي 3، فإن معدِّل البنية يساوي -4 ونقاط الصحة تساوي 6.
توفِّر معظم لغات البرمجة مولِّدات أرقام (شبه) عشوائية، لكن لغات برمجة قليلة مصمَّمة لرمي أحجار النرد. ومن هذه اللغات Troll.
في اللغات الوظيفية، معظم الدوال نقية. وهذا يعني أنها تُرجع دائمًا الناتج نفسه لمجموعة الوسائط نفسها، ولا تفعل شيئًا آخر. بعبارة أخرى، الدوال النقية حتمية.
لكن القيمة العشوائية، بحكم تعريفها، غير قابلة للتوقع وغير حتمية. وحتى الأعداد شبه العشوائية، أي إرجاع متتالية من الأعداد التي تبدو عشوائية، ليس بالأمر السهل تحقيقه في سياق نقي. وذلك لأن مولّد الأعداد شبه العشوائية (PRNG) يحتاج إلى تتبّع حالته الداخلية كي يُرجع العدد التالي في المتتالية.
يقدّم Lean أسلوبين ممكنين لحل هذه المشكلة:
استخدم مونادًا يتيح تغيير الحالة الداخلية لمولّد الأعداد شبه العشوائية.
وهناك دالة جاهزة، IO.rand، تفعل ذلك بالضبط.
استخدم دوال نقية تأخذ مولّدًا كوسيط وتُرجع ليس فقط القيمة شبه العشوائية الناتجة، بل أيضًا مولّدًا محدَّثًا «مهيَّأ» للعدد التالي في المتتالية.
يستخدم هذا التمرين الأسلوب الثاني. يُمرَّر مولّد إلى كل دالة يُفترض أن تنتج قيمة شبه عشوائية، ويُتوقع من الدالة أن تُرجع القيمة والمولّد المحدَّث معًا.
لاحظ أن أي مولّد معطى حتمي، أي أنه دائمًا يُنتج القيمة نفسها. ولتوليد القيمة شبه العشوائية التالية في المتتالية، لا بد من استخدام المولّد المحدَّث.
في هذا التمرين، يُتحقق من العشوائية بواسطة اختبار كاي تربيع عند مستوى دلالة مقداره p < 0.0001.
وهذا يعني أنه إذا وُلّدت درجة قدرة وفقًا للتعليمات، فإن احتمال أن يفشل تطبيق صحيح في الاختبار بمحض الصدفة العشوائية أقل من 0.01%.
لاحظ أن درجة القدرة، وفقًا للتعليمات، هي مجموع النتائج الثلاث الأكبر من أصل أربع رميات باستخدام d6 غير متحيّز (حجر نرد سداسي الأوجه).
سجّل في Exercism لتتعلّم وتتقن Lean عبر 100 تمرين، وإرشاد بشري حقيقي، وكل ذلك مجانًا.
نستكشف كيفية توليد رميات نرد عشوائية (ظاهريًا). ستتعرف على البذور والأعداد شبه العشوائية وبعض الأخطاء الشائعة. وأخيرًا، سنرى كيف أن الاختبار القائم على الخصائص ممتاز لاختبار الدوال التي تُرجع قيمًا عشوائية.