الاثنين، 1 أغسطس 2011

أنت والمغالطات المنطقية

صار الحوار السياسي مزعجا هذه الأيام؛ أشبه بصورة كاريكاتيرية عبارة عن وجهين يصرخان في بعضهما.

هناك مغالطات منطقية يقع فيها العديد من الأطراف. في المجتمعات الغربية صارت المغالطات مصطلحات دارجة لها أسماء، وهناك كتالوجات بها. سأسرد في هذا المقال بعض هذه المغالطات الشهيرة ومحاولة لتعريب اسمائها وأمثلة لها.

لماذا أفعل ذلك؟
  • أولا ليراجع كل منا نفسه قبل أن يتحاور، ويلغي من كلامه الخاص كل حجة فيها مغالطة (ذلك على افتراض أن الشخص نفسه يسعى للمصداقية بالطبع)
  • ثانيا لمساعدة القاريء على تقييم مصداقية الأخبار والمقالات والحوارات التي يقرأها كل يوم، ويرى إن كانت مبنية على حجج سليمة أم فاسدة
  • ثالثاً، لكي يستعين به المحاور إن كان الطرف الآخر استخدم - بقصد أو غير قصد - مغالطة في كلامه
شيء أخير: لقد تعمدت أن أوجد مصطلحاً عربياً لكل مغالطة ليس من أجل فكرة عامة على غرار تعريب العلوم وما شابه ولكن من أجل هدف مختلف: لأني أريد أن تكون الأسماء نفسها دارجة؛ بحيث يمكن لشخصان يتحاوران أن يقول أحدهما مثلاً "حجتك فيها مغالطة لا يتبع" فيفهمه الآخر والجمهور فوراً بلا حاجة لشرح المغالطات كلها من البداية.

الآن نأتي للكتالوج...

اسم المغالطة: Ad-hominem
الاسم العربي: هجوم تجاه الشخص لا الحجة

هذه أشهر مغالطة موجودة في مجتمعنا حالياً، أن يأتي الخصم ويجد عيباً ما (يراه) في الطرف الآخر، وعليه يكون الاستنتاج أن الطرف الآخر على خطأ. المغالطة هنا واضحة: حتى لو كان خصمك شخصاً سيئاً في نظرك فهذا ليس رداً كافياً على حجته...وكل التخوين والاتهام والسخرية من الناس لا تجعلهم مخطئين في وجهة نظر ما بالذات ولو كانت الاتهامات صحيحة.

كيف تتصرف: نبه الطرف الآخر أنه بهجومه الشخصي عليك يحاول أن يفلت من الرد على حجتك، واطلب منه رداً محدداً على كلامك

اسم المغالطة: Strawman argument
الاسم العربي: استبدال حجة أسهل

هذه أيضاً ذائعة هذه الأيام؛ أن تفسر كلام خصمك تفسيراً ليس بالضبط ما قصده لكن شيئاً له علاقة ما بما قاله، ويكون شيء أسهل بكثير في الرد. مثلاً:

يقول طرف من الأطراف "أنا مع الحكم الإسلامي"
فيرد الطرف الآخر "هل تريد ولاية الفقيه مثل إيران؟؟؟؟"

الطرف الأول لم يقل هذا مطلقاً، لكن الطرف الثاني أراد أن يرد على شيء يسهل الرد عليه، ففسر كلام الأول تفسيراً مخطئاً بهدف التيسير على نفسه.

اسمها بالانجليزية "مغالطة رجل القش" تشبيها بشخص خاف من مواجهة رجل حقيقي فصنع رجلاً ضعيفا من القش وهزمه :)

كيف تتصرف: قل "كلامي لا يُستدلّ منه بالضرورة ما تقول، أنت فسرت كلامي بشكل خاطيء، وغيرت الموضوع إلى نقطة كذا بدلاً من معنى كلامي الأصلي".

اسم المغالطة: Non-sequiter
الاسم العربي: لا يتبع

هنا يقول المتحدث أنه هناك معلومة حقيقية (أ) ثم يستنتج منها نتيجة (ب)، مع أن ب ليست بالضرورة نتيجة منطقية تتبع أ

مثلاً:
- هناك تأخير في محاكمة مبارك، ومعنى ذلك أن المجلس العسكري متواطيء مع مبارك نفسه
- فلان سافر إلى أمريكا ويعمل في شركة أمريكية، إذاً هو عميل أمريكي
- تم تعيين فلان في لجنة كذا وهو من الإخوان المسلمين، إذاً المجلس العسكري متواطيء مع الإخوان

...وهكذا

اسم المغالطة: False dilemma
الاسم العربي: الاختيارات المزيفة، الزنقة الإجبارية

هنا يضع المتحدث أمامك بديلان أو أكثر ويجبرك أن تختار بينهما، بينما في الواقع هناك اختيارات أخرى لم يذكرها قد تخرج من "الزنقة" الي يحاول أن يضعك فيها.

مثلاً:
- "لماذا لم ترشح فلاناً؟ هل تريدها دولة علمانية؟"
- "كيف تترك الإسلاميين يفعلون ما يريدون؟ هل تريدها دولة كهنوتية؟"
- "لماذا تعارض إمساك أحمد شفيق بمنصب رئيس الوزراء؟ ألا تعلم أن البديل هو الفوضى؟"

كيف تتصرف: وضح أن الطرف الآخر صاغ كلامه بحيث لا يكون أمامك سوى هذه الاختيارات، اقترح بدائل أخرى إن أمكن.

اسم المغالطة: Appeal to emotions
الاسم العربي: اللجوء للعاطفة، التماس عاطفي

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

اسم المغالطة: "Fallacy fallacy" (لا أعرف إن كان هذا اسماً رسمياً/دارجاً أم لا)
الاسم العربي: مغالطة "كلامك فيه مغالطة، إذن أنت على خطأ"

حين تجد مغالطة في كلام الطرف الآخر فليس معنى هذا أن رأيه الأصلي خطأ بالضرورة، فقط معناه أن هذه الحجة بالذات ليست دليلاً منطقياً على كلامه. قد يكون هناك أو لا يكون دليل آخر حقيقيّ. تذكر أن هدفنا هو المحافظة على مصداقية الحوار وليس "سحق" الخصم بأي وسيلة كانت ولو غير عادلة!

تذكر أيضاً أن المنطق ليس كل شيء أحياناً. مثلاً لو رأيت رجلاً متشح بالسواد ويمسك سكيناً ويسير ورائي، فهذا ليس دليلاً كافياً أنه سيء النية، لكن قد يكون من الحكمة أن أبتعد عنه :)

هذه كانت عينة من المغالطات المنطقية. ربما أستطيع أن أقدم المزيد من النماذج في مقال مستقبليّ.

الجمعة، 29 يوليو 2011

حاسبات للقرن الواحد والعشرين

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

تقليل العدد

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

لذلك فأنا أرى أن دفعة صغيرة من خمسين أو مائة مبرمج يتم انتقاؤهم بحرص ويتعلمون جيداً قد تقوم بدور في السوق مثل مئات المبرمجين في الصورة الحالية للكلية.

- هؤلاء قد يرفعون مستوى الشركات التي سيعملون فيها ويطورون اسلوبها
- هؤلاء قد يتعين منهم الأساتذة الذين يرفعون مستوى التعليم والبحث العلمي
- هؤلاء قد يفتحون الشركات ويغيرون من شكل الاقتصاد

في رأيي أنه على إدارة الكلية أن تفكر في هذه النقطة جيداً وتفعل كل ما تستطيع مع المجلس الأعلى للجامعات لتقلل العدد قدر المستطاع.

صورة الكلية أمام المجتمع

مشكلة كلية الحاسبات أنه من الصعب تعريفها لدى الشخص العادي: الطبيب يعالج، المهندس يبني، ماذا يفعل المبرمج؟ لهذا يأتي كل شخص بنظريته الخاصة [المبرمج يستخدم فوتوشوب، المبرمج يبيع هارد ديسكات، المبرمج يجلس أمام الفيسبوك...الخ].

المشكلة الثانية أن الكلية لا توجد لها قصص نجاح معلنة بما يكفي (أقصد أن لها قصص نجاح كثيرة لكن المعلن منها قليل) هذا يؤدي للحوار الآتي:
  • فلان دخل هندسة بترول وتوظف في شركة باشو للبترول بمرتب 10،000 جنيه! لماذا لا تصبح مثله؟
  • فلانة دخلت طب وفتح لها أبوها عيادة، أنت لست أقل من ذلك وأنا أدخر لك ثمن العيادة من الآن!

نريد أن نكون نحن أيضاً طرفاً في الحكاية، فكيف نفعل ذلك؟ الخبر الجيد أن 95% من الحل موجود بالفعل بين أيدينا ولا يبقى سوى ال5% الباقية: إن كان الإعلام المصري لا يعرف الكثير عن البرمجة (وهذا طبيعي لأي إعلام) فهو يعرف ما هو الاختراع ويحب قصص المخترعين.

انظر مثلاً لهذا المقال في جريدة الشروق عن مشروع تخرج يسمح لمستخدم الكمبيوتر بالتحكم فيه عن طريق تحريك يده. الآن انظر إلى تعليقات القراء على المقال؛ وكيف يحتفون بالمشروع ويعتبرونه إنجازاً مصرياً كبيراً...الخ.

نحن في حاسبات كل سنة تقريباً لدينا مشروع أو أكثر مثل هذا، التحكم في الكمبيوتر بتحريك اليد، والعين، والأذرع، وبالصوت، وبجهاز رسم المخ -- حتى أنني في سنة من السنين مللت هذه النوعية من المشاريع وصرت أقول للطلبة أن يفكروا في أفكار أخرى، لكن.......المجتمع لا يعرف ذلك!

[لم أقصد انتقاد صاحب المشروع في هندسة أو شيء من هذا، المشروع محترم لكن كلامي هنا عن المستوى العلمي لكليتي أنا]

لدينا مشاريع تتعامل مع اللغة العربية، لغات برمجة جديدة، مشاريع روبوت، مشاريع علمية، لكن المجتمع لا يعرف. ويظنون البلد متخلّفة :(

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

أريد أن يصير اسم حاسبات مرتبطاً بالاختراع، هذا هو التعريف الذي أريده في ذهن المجتمع.

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

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

لدينا من الخريجين في شركة مايكروسوفت بالولايات المتحدة وكندا حتى لتظن انه هناك فرع من الكلية هناك، لمَ لا يعرف أحد شيئاً عنهم؟

ماذا عن الخريجين الذين قد أسسوا شركات؟

هناك ألف شيء آخر يمكن عمله، مثل FAQ عن الكلية تتداول الأسئلة الشائعة عن سوق العمل والنقابة والمعاهد...الخ. فكرت أصلاً في جعل هذه الوثيقة في صورة قصص مصورة comics لكي تغري الناس بقراءتها. من يبحث يجد ألف فكرة.

[تعقيب: قد أتبعت كلامي بعمل وبدأت خطوة صغيرة في هذا الاتجاه.]

العامل البشري

الكفاءات هي التي تصنع أي مؤسسة، وغياب الكفاءات هو الذي يهدمها. لا يضاهي الكفاءات في الأهمية سوى الجانب الإداري. معادلة النجاح المؤسسي هي

كفاءات عالية + بيئة إدارية مشجعة = مؤسسة ناجحة.

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

نحن نحتاج إلى هذا من جديد! لابد من البحث عن الأساتذة الممتازين في كل مكان داخل وخارج مصر، ودعوتهم لتقديم المواد في الكلية. لابد من توفير المغريات المناسبة التي تجعلهم يرضون بالمجيء، ليس فقط المال لكن بيئة علمية جيدة، فرصة لتغيير المجتمع، بحث علمي حقيقي...الخ

ولابد أن تكون البيئة مهيئة لا فقط لجذبهم لكن للاحتفاظ بهم، فالشخص الكفء لديه مطلق الحرية أن يعمل في أية مكان يشاء، ولو رأى المكان لا يشجع فلا يوجد فتفوتة شيء يُكرهه على البقاء.

البحث عن الكفاءات وجذبها، توفير البيئة التي تستثمر كفاءتهم، توفير ظروف الإبقاء عليهم. هذه يجب أن تكون الأولوية القصوى لأية مؤسسة لا فقط الكليات.

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

الثلاثاء، 26 يوليو 2011

لغة كلمات: مرجع كامل أخيراً!

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

الملف الذي استخدمته في العرض متاح للتحميل بأن تضغط هنا وهو في صيغة PDF

الأربعاء، 20 يوليو 2011

بيب! بيب! بيب!


Kalimat calling the Windows API! (This is work in progress)

GP Ideas: 1- Sketchcode

Concept

Let users write programs by sketching; either using paper+scanner or using a tablet computer.

More info

I have an incomplete design of a sketch-based programming language that combines text and graphics elements. Data structures like linked lists or trees would be expressed by their familiar sketch notations, while functions would resemble their familiar text representation enriched by some additional notation gained from using a pen.

I can show my designs to interested teams, but I won't post pictures here on my blog for obvious reasons :)

The project will have two major subsystems and 3 major stages. The subsystems are
(a) Sketch recognizer
(b) Code generator [or interpreter].

The stages are
(a) Language design
(b) Implementing sketch recognizer
(c) Implementing code generation

Stages (b) and (c) could probably be done in parallel assuming a complete language specification was made beforehand.

I cannot officially supervises the project of course, but I am prepared to participate in the design of the full language.

Challenges and risks

The first challenge is in the design of a language that is usable for the sketch medium and expressive enough to represent complex programs without cluttering the area with complex, unclear sketches.

The second is the usual risk of pattern-based projects: The accuracy of recognition, choice of training algorithms, and so on.

Techniques needed

Patterns recognition, image processing, possibly compilers

Notes

This is related to my technology vision of Awraq

الخميس، 7 يوليو 2011

قوائم متسلسلة في كلمات

تريد أن تحل مسألة ACM بكلمات؟ سوف تحتاج بضعة أشياء، منها القوائم المتسلسلة Linked lists. هيا نبدأ في عملها - أول ما نحتاجه هو فصيلة class يعبر عن حلقة في السلسلة. ما يكافيء node في لغات البرمجة الأجنبية :)
فصيلة حلقة :
له بيان
له سابق، تالي
نهاية
هنا لا نعرف methods في فصيلتنا، فقط نعرف مجالات للبيانات data fields.
بالمرة هيا نعرف فصيلة القائمة:
فصيلة قائمة :
له أول ، آخر
نهاية
قبل أن نتابع علينا أن نعرف بعض المعلومات عن الكائنات في لغة كلمات:
  • لإنشاء كائن object من فصيلة معينة نكتب اسم الفصيلة يليه كلمة جديد مثل م = موظف جديد
  • للوصول إلى field نكتب اسمه قبل الكائن، أي أن س مركز النقطة في كلمات يكافيء point.center.x في اللغات التقليدية
  • الثابت لاشيء يعادل null في اللغات المماثلة للJava أو #C.
الآن نريد أن نضيف إمكانيات الإضافة والمسح من القائمة. هنا ستكون الفصيلة قائمة أكثر من مجرد حاوٍ للبيانات، سوف نضيف إليها methods. قبل أن نضيفها يجب أولاً أن نعرف كيف نستدعيها!

تخيل أن فصيلة القائمة لديها method اسمها اضف(...)، سوف نستدعيها هكذا:

ق : اضف(12)

هذا يكافيء lst.add(12) //add to list في اللغات الأخرى. وهو في كلمات اسمه إرسال رسالة إلى الكائن، والكود التي ستتفذ ستكون استجابة لهذه الرسالة. مثل ال++C لابد أن نعرف الاستجابة على جزئين: نعلن عنها داخل الفصيلة ونكتب تفاصيلها خارج الفصيلة.

أولاً الإعلان:
فصيلة قائمة :
له أول ، آخر
-- هنا أعلننا عن الاستجابة
يستجيب ل: اضف ( عنصر )
نهاية
ثانياً التفصيل:
استجابة قائمة ق ل: اضف ( عنصر ) :
-- سوف نكتب التنفيذ هنا
نهاية
هنا نعرف method جديدة عن طريق كلمة استجابة. لابد أن نعطي اسماً للكائن متلقي الرسالة هو هنا ق (في اللغات التقليدية يكون الاسم اوتوماتيكيا this ، لكن هنا لابد من إعطاء اسم).

لاحظ كيف أن الكلام يبدو طبيعياً جداً... استجابة قائمة ق لـ"أضف عنصر" هو افعل كذا كذا..نهاية. هذا لأن كلمات لغة برمجة تستمد جمالها من جمال اللغة العربية™

الآن يمككنا أن نكتب الكود أخيراً:
استجابة قائمة ق ل: اضف ( العنصر ) :
ح = حلقة جديد
بيان ح = العنصر

إذا أول ق = لاشيء :
أول ق = ح
        آخر ق = ح
    وإلا :
تالي آخر ق = ح
        سابق ح = آخر ق
        آخر ق = ح
    تم
نهاية
أنظروا! استطيع كتابة كود الإضافة إلى قائمة!! سنترك كود المسح كتمرين للطالب :)

كلمة استجابة في كلمات، مثل كلمة إجراء، تعبر عن void function, void method. ماذا لو أردنا عمل شيء يعود بقيمة؟ هنا بدلاً من استخدام كلمة استجابة سوف نستخدم كلمة رد.
فصيلة قائمة :
له أول ، آخر
يستجيب ل: اضف ( عنصر )
-- هنا عرفنا رداً جديداً
يرد على عددهم ( )
نهاية
ثم نكتب تنفيذ الرد:
رد قائمة ق على عددهم ( ) :
إذا أول ق = لاشيء :
ارجع ب: 0
    وإلا :
النتيجة = 0
       أ = أول ق
طالما ليس أ = لاشيء :
النتيجة = النتيجة + 1
           أ = تالي أ
       تابع
ارجع ب: النتيجة
    تم
نهاية
الآن..نستطيع اختبار البرنامج:
الوجبات = قائمة جديد
الوجبات : اضف ( "شاورمة" )
الوجبات : اضف ( "مجبوس" )
الوجبات : اضف ( "فول وطعمية" )

اطبع الوجبات : عددهم ( )
قد يهم محبي النحو سبب تسميتنا للرد بإسم عددهم ؛ هذا يجعل التعبير كله يأخذ صورة بدل الجزء من الكل/بدل الاشتمال في اللغة العربية. هل تذكر في المدرسة "أعجبني الخروف صوفه"؟ نحن هنا نقول "اطبع الوجبات عددهم" :)

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

فصيلة قائمة :
له أول ، آخر
يستجيب ل: اضف ( عنصر )
يرد على عددهم ( )
نهاية

رد قائمة ق على عددهم ( ) :
إذا أول ق = لاشيء :
ارجع ب: 0
وإلا :
النتيجة = 0
أ = أول ق
طالما ليس أ = لاشيء :
النتيجة = النتيجة + 1
أ = تالي أ
تابع
ارجع ب: النتيجة
تم
نهاية

استجابة قائمة ق ل: اضف ( العنصر ) :
ح = حلقة جديد
بيان ح = العنصر

إذا أول ق = لاشيء :
أول ق = ح
آخر ق = ح
وإلا :
تالي آخر ق = ح
سابق ح = آخر ق
آخر ق = ح
تم
نهاية

الوجبات = قائمة جديد
الوجبات : اضف ( "شاورمة" )
الوجبات : اضف ( "مجبوس" )
الوجبات : اضف ( "فول وطعمية" )

اطبع الوجبات : عددهم ( )

فلتكن أشياء حقيقية

من يريد ألا تصبح مملاً عليه ألا يجعل تفكيره يقتصر على الأشياء المجردة؛ بل يفكر في أشياء حقيقية.

من الأشياء المجردة في الحياة: المال، فهو أرقام، والمنصب، فهو كلمة على ورقة. من الأشياء الحقيقية في الحياة: طعم الآيس كريم، يوم من المزاح مع أبنائك، سرير مريح.

لكنك تقول أن المال والمنصب أشياء حقيقية وليست مجردة: المال يستطيع أن يبتاع سيارات وبيوت وكتب وآيس كريم...حتى السرير المريح يستطيع المال أن يشتريه، أليس هذا مذهلاً؟؟؟

نفس الشيء بالنسبة للمنصب، إنه يعطينا قدرة أكبر على التأثير في الناس وإصلاح المجتمع، كيف هو غير حقيقيّ؟

قصدي من هذا المقال ليس الحديث عن طبيعة الأشياء لكن عن نظرتي ونظرتك لها.

هناك من يريد المال لكن حين يفكر فيه لا يفكر في رصيد كبير في البنك: يفكر في الأجهزة الإلكترونية المغرية التي يستطيع أن يشتريها، أو البيت الواسع الذي يريد السكن فيه، أو المصنع التي يريد أن يفتحه..

في مقابل ذلك هناك أشخاص يحبون المال في حد ذاته: يعيشون حياتهم في عمل دؤوب لا هم لهم سوى جمعه، مع أنهم بالفعل قد جمعوا كل ما يحتاجونه وأكثر! لديهم ما يكفي لشراء كل ما يمكن أن يسعدهم وأضعاف ذلك لكنهم لم يكتفوا.

هنا نجد أن الشخص لا يجد السعادة في ما يشتريه المال له بل في أرقام: العشرة ملايين أفضل من المليون، المليار أفضل. والأرقام - كما نعلم - هي أشياء مجردة لا حقيقية.

نفس الشيء بالنسبة للمنصب: هناك من يفرح بمنصب وزير لأنه يجلس على مكتب الوزير، والكروت في محفظته مكتوب عليها وزير، والكل يكلمه باحترام ويفتتح الكلام بعبارة "السيد فلان، وزير كذا". يفكر هو في المجتمع كأنه خط يمتد من الأعلى للأسفل وكل منا نقطة على هذا الخط ، وهو بمنصبه هذا قد زحزح نقطته لمكان أعلى في خط المجتمع. والنقط والخطوط هي كما نعلم....أشياء مجردة.

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

هذه أشياء حقيقية

الخميس، 23 يونيو 2011

الكرات المتحركة - مثال بكلمات

نريد أن نبدأ بتحريك كرة واحدة، ثم بعد ذلك نتصرف في باقي الكرات.
إجراء حرك.الكرة ( طيف ، س ، ص ، السرعة ) :
-- سوف نكتب كود هنا
نهاية
(اعتبر الإجراء مثل void function).
هذا الإجراء يأخذ اربع عوامل:
  • طيف هو الطيف الذي يعبر عن رسمة الكرة؛ الطيف شكل متحرك يرسم على الشاشة (sprite) وسنعرف الآن كيف نتعامل معه
  • س، ص هو المكان الذي نريد أن يبدأ فيه رسم الكرة
  • السرعة هو مصفوفة (array) من عنصرين يعبر عن متجه vector فيه سرعة الكرة في الاتجاهين السيني والصادي
نبدأ في تفاصيل الإجراء:
إجراء حرك.الكرة ( طيف ، س ، ص ، السرعة ) :
    كرر :
        ارسم.طيف طيف في ( س ، ص )
        س = س + السرعة [ 1 ]
        ص = ص + السرعة [ 2 ]
        انتظر(15)
    تابع
نهاية
الأمر هنا بسيط: الأمر ارسم.طيف/في يأخذ طيفاً ويرسمة في نقطة محددة هي هنا نقطة البداية، ثم نغير هذه النقطة كل مرة حسب متجه السرعة، بأن نضيف السرعة في الاتجاه السيني إلى س ونفس الشيء في ص. لاحظ أن المصفوفات في كلمات تبدأ من الواحد.

نكرر هذه العملية باستمرار مع انتظار بسيط - 15 ميلليثانية - بين رسمة والأخرى

المشكلة هنا هي أن الكرة ستخرج من الشاشة بعد قليل وتختفي، نحن نريدها أن "تصطدم" بالشاشة ومن ثم تغير اتجاهها. خطتنا بسيطة:
  • إذا اصطدمت الكرة بقمة الشاشة أو قاعها، نقلب إشارة السرعة في الاتجاه الصادي فنحيلها من موجبة لسالبة أو بالعكس، وبذلك تنزل الكرة مثلاً إن كانت تصعد.
  • إذا اصطدمت بيمين الشاشة أو يسارها نغير إشارة المكون السيني للسرعة
  • في الحالتين إن كانت الكرة تكاد أن تُرسم خارج الشاشة نعيد مكانها لحافة الشاشة
كيف ينعكس ذلك على الكود؟ تعال نرى مثلاً ماذا يحدث لو تجاوزت الكرة الحافة اليمنى للشاشة.
إذا س < 0 :
    س = 0
    السرعة [ 1 ] = - السرعة [ 1 ]
تم
الحافة اليمنى هي النقطة س=صفر، فأن كانت س أقل من الصفر فمعنى هذا أن الكرة توشك أن تخرج، فنعيدها مرة أخرى إلى الحافة ونعكس إشارة المكون الأول للسرعة. لاحظ أن نظام الإحداثيات يساير الكتابة العربية (س تزداد من اليمين لليسار).

ماذا يحدث لو تجاوزت الكرة يسار الشاشة؟ هذا:
إذا س + عرض.الطيف ( طيف ) > 799 :
    س = 799 - عرض.الطيف ( طيف )
    السرعة [ 1 ] = - السرعة [ 1 ]
تم
شاشة الرسم في كلمات عرضها 800 نقطة وارتفاعها 600، لذلك النقطة في أقصى اليسار هي النقطة 799 لأن العد يبدأ من الصفر.

إذا تجاوزت حافة الكرة اليسرى (المحددة بقيمة س + عرض الكرة) هذا الحد نعيد الحافة اليسرى للنقطة الأخيرة. لاحظ أن التخصيص
س = 799 - عرض.الطيف ( طيف )
معناه اجعل س + عرض الطيف = 799، أي اجعل الحافة اليسرى بهذه القيمة.
سنفعل نفس الشيء مع قيم ص ليكون الإجراء الكامل كالآتي:
إجراء حرك.الكرة ( طيف ، س ، ص ، السرعة ) :
    كرر :
        ارسم.طيف طيف في ( س ، ص )
        س = س + السرعة [ 1 ]
        ص = ص + السرعة [ 2 ]
        إذا س < 0 :
            س = 0
            السرعة [ 1 ] = - السرعة [ 1 ]
        وإلا إذا س + عرض.الطيف ( طيف ) > 799 :
        س = 799 - عرض.الطيف ( طيف )
            السرعة [ 1 ] = - السرعة [ 1 ]
        تم
        إذا ص < 0 :
            ص = 0
            السرعة [ 2 ] = - السرعة [ 2 ]
        وإلا إذا ص + ارتفاع.الطيف ( طيف ) > 599 :
            ص = 599 - ارتفاع.الطيف ( طيف )
            السرعة [ 2 ] = - السرعة [ 2 ]
        تم
        انتظر ( 15 )
    تابع
نهاية
عظيم!! لقد أنهينا الإجراء. لم يتبق سوى استدعاؤه:
ط = حمل.طيف ( "ball1.bmp" )
س = عشوائي ( 800 )
ص = عشوائي ( 600 )
السرعة.س = عشوائي ( 20 ) + 1
السرعة.ص = عشوائي ( 20 ) + 1
السرعة = [ السرعة.س ، السرعة.ص ]
حرك.الكرة ( ط ، س ، ص ، السرعة )
هنا قمنا باستخدام الدالة الجاهزة حمل.طيف لنقوم بتحميل صورة للكرة وتكوين طيف منها، ثم ولدنا بعض القيمة العشوائية لمكان الكرة وسرعتها وقمنا بتمريرهم إلى الإجراء. لاحظ كيف يمكن عمل مصفوفة من عنصرين بالتعبير [ أ، ب] كما فعلنا للمتغير السرعة

يمكننا الآن أن ننفذ البرنامج:
للأسف لقطة الشاشة لا تبين روعة الكرة وهي تجري..كان ينبغي أن أضع فيديو لهذا المثال على اليوتيوب :]

الآن نريد أن نجعل البرنامج يتحرك فيه كرات كثيرة...هذا في الواقع أسهل مما نتخيل بسبب إمكانات البرمجة المتوازية في لغة كلمات. الأمر شغل يأخذ الصيغة التالية:
شغل <استدعاء إجراء>
ومعناه "استدع هذا الإجراء بحيث يعمل على التوازي مع باقي البرنامج وأي إجراءات أخرى". كل ما علينا الآن هو تشغيل عدة نسخ من الإجراء على التوازي ليكون لدينا كرات كثيرة!

(ملاحظة: تنفيذ الإجراءات في الواقع لن يكون متوازياً، بل ستقوم الآلة الافتراضية virtual machine الخاصة بكلمات بالانتقال بسرعة بين إجراء والآخر ليبدو الأمر كأنه على التوازي. في المستقبل ننوي تغيير الآلة الافتراضية لتحقيق توازٍ حقيقي).

سيبدو تنفيذ الإجراء الآن كالآتي، لنحرك عشر كرات عشوائياً:
لكل أ من 1 إلى 10 :
    ط = حمل.طيف ( "ball1.bmp" )
    س = عشوائي ( 800 )
    ص = عشوائي ( 600 )
    السرعة.س = عشوائي ( 20 ) + 1
    السرعة.ص = عشوائي ( 20 ) + 1
    السرعة = [ السرعة.س ، السرعة.ص ]
    شغل حرك.الكرة ( ط ، س ، ص ، السرعة ) 
تابع

جميل، لكن الكرات كلها من نفس اللون، نريد أن يكون الأمر متنوعاً قليلاً..نرى الآن البرنامج في صورته النهائية:
ملفات.الأطياف=["ball4.bmp"،"ball3.bmp"،"ball2.bmp"،"ball1.bmp"]

لكل أ من 1 إلى 10 :
    ط = حمل.طيف ( ملفات.الأطياف [ عشوائي ( 4 ) + 1 ] )
    س = عشوائي ( 800 )
    ص = عشوائي ( 600 )
    السرعة.س = عشوائي ( 20 ) + 1
    السرعة.ص = عشوائي ( 20 ) + 1
    السرعة = [ السرعة.س ، السرعة.ص ]
    شغل حرك.الكرة ( ط ، س ، ص ، السرعة )
تابع

إجراء حرك.الكرة ( طيف ، س ، ص ، السرعة ) :
    كرر :
    ارسم.طيف طيف في ( س ، ص )
        س = س + السرعة [ 1 ]
        ص = ص + السرعة [ 2 ]
        إذا س < 0 :
            س = 0
            السرعة [ 1 ] = - السرعة [ 1 ]
        وإلا إذا س + عرض.الطيف ( طيف ) > 799 :
        س = 799 - عرض.الطيف ( طيف )
            السرعة [ 1 ] = - السرعة [ 1 ]
        تم
        إذا ص < 0 :
            ص = 0
            السرعة [ 2 ] = - السرعة [ 2 ]
        وإلا إذا ص + ارتفاع.الطيف ( طيف ) > 599 :
            ص = 599 - ارتفاع.الطيف ( طيف )
            السرعة [ 2 ] = - السرعة [ 2 ]
        تم
        انتظر ( 15 )
    تابع
نهاية
لتحميل المثال كاملاً:
اضغط هذا الرابط

لتحميل لغة كلمات:
http://code.google.com/p/kalimat/downloads
أو من الموقع الرسمي http://www.kalimat-lang.com

الجمعة، 17 يونيو 2011

آلة حاسبة بلغة كلمات


لا تحتاج خبرة سابقة بالبرمجة بلغة كلمات لتتابع هذا المثال (لكن تحتاج لأن تعرف البرمجة بشكل عام). إذا أردت أن تجربه عملياً فيمكنك تحميل أحدث نسخة من اللغة من http://code.google.com/p/kalimat/downloads


هام: هذا المثال يحتاج نسخة يونيو 2011 أو أحدث ليعمل. لو كنت قد حملت نسخة قديمة من كلمات فستحتاج أن تحمل نسخة جديدة.

الآن هيا نبدأ!

رسم الأزرار على الشاشة
زر1 = زر جديد
زر1 : حدد.المكان ( 10 ، 10 )
زر1 : حدد.الحجم ( 30 ، 30 )
زر1 : حدد.النص ( "1" )
ن = النافذة.الحالية ( )
ن : اضف ( زر1 )

ستؤدي الكود السابقة لعرض زر على الشاشة. لاحظ ان علامة النقطتين ' : ' معناها method call، مثل علامة النقطة في لغات البرمجة المعروفة. الأمر جديد هنا هو نفسه operator new في اللغات الأخرى.

نحن سنرسم أزراراً كثيرة في البرنامج، لذلك هيا نكتب دالة (function) توفر علينا عناء الكتابة المتكررة:
دالة صنع.زر(س ، ص ، العرض ، الارتفاع ، النص ، النافذة):
   ز = زر جديد
   ز : حدد.المكان ( س ، ص )
   ز : حدد.الحجم ( العرض ، الارتفاع )
   ز : حدد.النص ( النص )
   النافذة : اضف ( ز )
   ارجع ب: ز
نهاية
لاحظ هنا أن العوامل (parameters) لا تأخذ تعريف للأنواع، بل فقط تأخذ اسماً، وذلك لأن اللغة dynamically typed مثل لغات البايثون مثلاً أو الجافاسكريبت. أيضاً لاحظ أن النقطة هي جزء من اسم الدالة، أي ان اسمها صنع.زر هكذا كلمة واحدة، النقطة في كلمات هي جزء من رموز المعرفات (identifier characters) ولا دور لها في معنى البرنامج.

الآن وقد صار لدينا دالة تسهل وضع الأزرار يمكننا أن نرسم شكل الآلة الحاسبة، نبدأ أولاً بالأزرار ثم نضيف لاحقاً 'شاشة العرض' التي ستظهر عليها النتيجة:
ن = النافذة.الحالية ( )
زر1 = صنع.زر (40 ، 130 ، 30 ، 30 ، "1" ، ن)
زر2 = صنع.زر (70 ، 130 ، 30 ، 30 ، "2" ، ن)
زر3 = صنع.زر (100، 130 ، 30 ، 30 ، "3" ، ن)
زر4 = صنع.زر (40 ، 100 ، 30 ، 30 ، "4" ، ن)
زر5 = صنع.زر (70 ، 100 ، 30 ، 30 ، "5" ، ن)
زر6 = صنع.زر (100، 100 ، 30 ، 30 ، "6" ، ن)
زر7 = صنع.زر (40 ، 70  ، 30 ، 30 ، "7" ، ن)
زر8 = صنع.زر (70 ، 70  ، 30 ، 30 ، "8" ، ن)
زر9 = صنع.زر (100 ، 70 ، 30 ، 30 ، "9" ، ن)
زر0 = صنع.زر (70 ، 160 ، 30 ، 30 ، "0" ، ن)

زر.الجمع = صنع.زر (10 ، 70  ، 30 ، 30 ، "+" ، ن)
زر.الطرح = صنع.زر (10 ، 100 ، 30 ، 30 ، "-" ، ن)
زر.الضرب = صنع.زر (10 ، 130 ، 30 ، 30 ، "×" ، ن)
زر.القسمة = صنع.زر(10 ، 160 ، 30 ، 30 ، "÷" ، ن )
زر.يساوي = صنع.زر (40 ، 160 ، 30 ، 30 ، "=" ، ن)
زر.الفاصلة.العشرية = صنع.زر(100، 160، 30، 30، "."، ن)

والآن حان دور شاشة العرض:
الشاشة = سطر.نصي جديد
الشاشة : حدد.المكان ( 10 ، 30 )
الشاشة : حدد.الحجم ( 120 ، 30 )
الشاشة : حدد.النص ( "" )
ن : اضف ( الشاشة )

الفصيلة سطر.نصي معناها صندوق لتحرير النصوص من سطر واحد، إن أردت تحرير أكثر من سطر في برنامجك يمكنك استخدام الفصيلة صندوق.نصي

الآن يمكننا تجربة البرنامج:

شكله ظريف، لكن هناك مشكلتان: النافذة حجمها الافتراضي أكبر من اللازم، كما أن عنوانها "تنفيذ البرنامج" عام أكثر مما ينبغي...من السهل تغيير ذلك على أية حال. أضف هذه السطور لآخر البرنامج:

ن : حدد.الحجم ( 150 ، 210 )
ن : حدد.العنوان ( "الحاسبة" )


هذا أفضل بكثير!

ادخال المستخدم للأرقام

الآن بعد عمل "شكل" البرنامج حان وقت اضافة "المضمون". أول شيء نريده هو عرض الأرقام حين يدخلها المستخدم. الأمر نلخصه في القواعد الآتية:
1- إذا ضغط المستخدم زر رقمي [0..9]، اضف الرقم المناظر للزر إلى شاشة العرض
2- إذا ضغط المستخدم زر الفاصلة العشرية اضفه لشاشة العرض إذا كانت هذه أول مرة يضغط فيها، وإلا لا تفعل شيئاً.

قبل أن نبدأ بتنفيذ كل ذلك علينا أن نأخذ جانباً ونعرف كيف نتعامل مع الحوادث (events) مثل ضغط زر او اختيار شيء من قائمة أو ما شابه. يحدث ذلك في كلمات عن طريق مفهوم القنوات.

اضف هذا الجزء لنهاية البرنامج:
كرر :
   تسلم إشارة من ضغط  زر1
   الشاشة : الحق.نص ( "1" )
تابع
هناك قناة في فصيلة الأزرار اسمها ضغط. القناة هي كائن يمكن عن طريقه لجزء من البرنامج (مثل الزر) أن يرسل إشارة لجزء آخر (مثل السطور السابقة) عندما يريد ابلاغه بحدث معين.

الأمر
تسلم إشارة من ضغط زر1
سوف يؤدي لأن ينتظر البرنامج حتى يرسل الزر الإشارة المطلوبة قبل المتابعة. سوف تأتي تلك الإشارة حين يضغط المستخدم زر ادخال الواحد1، في تلك الحالة سيضيف البرنامج الرمز "1" لشاشة العرض ويعود إلى حالة الانتظار في حلقة لا نهائية.

لو قمت بتجربة البرنامج الآن ستجد أنه يضيف "1" إلى الشاشة كلما ضغطت الزر المطلوب.

(دور القنوات أكثر بكثير مما قيل هنا، لكن لن نتوسع في الحديث عنها في هذا المثال المبدئي)

كيف نجعله يضيف باقي الأرقام؟ المشكلة أن هذه الكود لن تنفع:
كرر :
   تسلم إشارة من ضغط زر1
   الشاشة : الحق.نص ( "1" )

   تسلم إشارة من ضغط زر2
   الشاشة : الحق.نص ( "2" )
تابع
لماذا لن تنفع؟ لأننا هنا نأمره أن يتسلم الإشارات بالترتيب، أي أننا نقول للبرنامج "تسلم اشارة من ضغط زر1، ثم تسلم إشارة من زر2". هذا سيعمل فقط لو أراد المستخدم أن يدخل شيئاً مثل "12" أو "1212"، "121212"...الخ :(

ما الحل إذاً؟ لابد من طريقة نقول له أنه هناك أكثر من قناة وعليك استلام اشارة من أي واحدة منها حين تأتي. هذا هو دور الأمر تخير
كرر :
    تخير :
    تسلم إشارة من ضغط زر1 :
       الشاشة : الحق.نص ( "1" )
    أو تسلم إشارة من ضغط زر2 :
       الشاشة : الحق.نص ( "2" )
    تم
تابع
هنا سوف ينتظر البرنامج أي من الإشارتين، ضغط زر1 أو ضغط زر2، فإن جاءت الإشارة سينفذ جزء الكود المرتبط بها (أي يضيف 1 أو 2 إلى الشاشة حسب الإشارة القادمة) ثم يتابع في حلقة لا تنتهي.

من السهل تعميم ذلك لندخل الأرقام كلها:
كرر :
    تخير :
    تسلم إشارة من ضغط زر1 :
       الشاشة : الحق.نص ( "1" )
    أو تسلم إشارة من ضغط زر2 :
       الشاشة : الحق.نص ( "2" )
    أو تسلم إشارة من ضغط زر3 :
       الشاشة : الحق.نص ( "3" )
    أو تسلم إشارة من ضغط زر4 :
       الشاشة : الحق.نص ( "4" )
    أو تسلم إشارة من ضغط زر5 :
       الشاشة : الحق.نص ( "5" )
    أو تسلم إشارة من ضغط زر6 :
       الشاشة : الحق.نص ( "6" )
    أو تسلم إشارة من ضغط زر7 :
       الشاشة : الحق.نص ( "7" )
    أو تسلم إشارة من ضغط زر8 :
       الشاشة : الحق.نص ( "8" )
    أو تسلم إشارة من ضغط زر9 :
       الشاشة : الحق.نص ( "9" )
    أو تسلم إشارة من ضغط زر0 :
       الشاشة : الحق.نص ( "0" )
    تم
تابع
الكود طويلة لكن كلها تشبه بعضها؛ لا تعقيد كبير فيها. هناك طرق لجعلها أكثر تنظيماً لكن صورتها الحالية بسيطة، ونحن نريده مثالاً بسيطاً في الوقت الحالي...

الفاصلة العشرية

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

كرر :
    تخير :
    تسلم إشارة من ضغط زر.الفاصلة.العشرية :
        إذا كتبنا.فاصلة.عشرية = خطأ :
            الشاشة : الحق.نص ( "." )
            كتبنا.فاصلة.عشرية = صحيح
        تم
    أو تسلم إشارة من ضغط زر1 :
        الشاشة : الحق.نص ( "1" )
    أو تسلم إشارة من ضغط زر2 :
        الشاشة : الحق.نص ( "2" )
    ........وهكذا وهكذا الخ الخ
    تم
تابع

العمليات

هيا الآن ننفذ عملية الجمع وسيكون من السهل تعميم الطريقة بعد ذلك لتشمل جميع العمليات. سوف نحتاج هنا متغيران جديدان: متغير اسمه العملية والآخر اسمه العدد.الأول

المتغير المسمى العملية يدل على العملية الحسابية الحالية. في البداية ستكون قيمته نصاً فارغاً، فإذا ضغط المستخدم زر الجمع سنعطيه القيمة "+"، بحيث نعرف ما المطلوب من الحاسبة عند ضغط زر 'يساوي'.

ستأخذ الكود الصورة التالية:
كتبنا.فاصلة.عشرية = خطأ
العملية = ""
العدد.الأول = لاشيء
 
كرر :
    تخير :
    تسلم إشارة من ضغط زر.الجمع :
        العملية = "+"
        العدد.الأول = الشاشة : نصه ( )
        العدد.الأول = كعدد ( العدد.الأول )
        كتبنا.فاصلة.عشرية = خطأ
        الشاشة : حدد.النص ( "" )

    أو تسلم إشارة من ضغط زر.يساوي :
        العدد.الثاني = الشاشة : نصه ( )
        العدد.الثاني = كعدد ( العدد.الثاني )
        إذا العملية = "+" :
            النتيجة = العدد.الأول + العدد.الثاني
            النتيجة = كنص ( النتيجة )
            الشاشة : حدد.النص ( النتيجة )
            العملية = ""
        تم
    أو تسلم إشارة من ضغط زر.الفاصلة.العشرية :
        ....وهكذا الكلام السابق الذي نعرفه....
    تم
تابع
تعال نأخذ كل جزء على حدىً.. أولاً زر الجمع نفسه:
...
تسلم إشارة من ضغط زر.الجمع :
    العملية = "+"
    العدد.الأول = الشاشة : نصه ( )
    العدد.الأول = كعدد ( العدد.الأول )
    كتبنا.فاصلة.عشرية = خطأ
    الشاشة : حدد.النص ( "" )
...
هذا الجزء يقوم بالآتي عند ضغط زر الجمع:
1- يحدد العملية بأنها "+"
2- يأخذ النص المكتوب على الشاشة، يحوله لعدد، ويخزنه في المتغير العدد.الأول لأننا سنحتاجه بعد ذلك لإجراء عملية الجمع
3- يفرغ الشاشة استعداداً لإدخال رقم جديد
4- يسمح لنا بإدخال فاصلة عشرية (إن أردنا) أثناء إدخال الرقم الثاني وذلك بأن يجعل قيمة كتبنا.فاصلة.عشرية تساوي خطأ

الجزء الآخر عند ضغط زر 'يساوي'
....
أو تسلم إشارة من ضغط زر.يساوي :
    العدد.الثاني = الشاشة : نصه ( )
    العدد.الثاني = كعدد ( العدد.الثاني )
    إذا العملية = "+" :
        النتيجة = العدد.الأول + العدد.الثاني
        النتيجة = كنص ( النتيجة )
        الشاشة : حدد.النص ( النتيجة )
        العملية = ""
    تم
....
هذا بدوره يقوم بالآتي:
1- يأخذ العدد الموجود على الشاشة ويخزنه في المتغير العدد.الثاني
2- يتأكد أن العملية عملية جمع (سيكون هذا مهماً حين نضيف باقي العمليات) ويحسب النتيجة المطلوبة
3- يعرض النتيجة على الشاشة بعد تحويلها إلى صورة نصية
4- يعيد العملية إلى القيمة غير المعرفة "" إلى أن نختار عملية جديدة

هناك فقط مشكلة هي أن البرنامج سيعمل بطريقة صحيحة مرة واحدة فقط: لو أدخلت 12 ثم + ثم 13 ثم = فستجد النتيجة 25، لكن إن ضغطت بعدها 1 فستجد مكتوب على الشاشة 251

هذا خطأ..كان المفروض أن يعتبر البرنامج اننا انتهينا من الحسبة القديمة ويفرّغ الشاشة قبل بدء الحسبة الجديدة، بحيث يظهر على الشاشة 1

أيضاً تصرف آلتنا الحاسبة ليس مثل الآلة العادية. نحن حين نضغط 12 ثم + سوف نجد الشاشة قد مسحت، بينما في الحاسبة العادية سوف نضغط 12 ثم + ولا يتم مسح الشاشة إلا عند بدء إدخال العدد الثاني.

نحن نحتاج طريقة نقول بها للبرنامج "نحن على وشك إدخال عدد جديد، لذلك قم بمسح الشاشة المرة القادمة لو ضغط المستخدم زر عددي، ثم اعرض ما ادخل".

لكي نحل المشكلة نحتاج لمتغير جديد اسمه تفريغ، معناه "هل علينا أن نفرغ الشاشة حين يضغط المستخدم على زر عددي في المرة القادمة"؟

سوف نحتاج أيضاً أن نعدّل البرنامج قليلاً (التعديلات بالخط الثقيل ولونها أحمر):
كتبنا.فاصلة.عشرية = خطأ
العملية = ""
العدد.الأول = لاشيء
تفريغ = خطأ 
 
كرر :
    تخير :
    تسلم إشارة من ضغط زر.الجمع :
        العملية = "+"
        العدد.الأول = الشاشة : نصه ( )
        العدد.الأول = كعدد ( العدد.الأول )
        كتبنا.فاصلة.عشرية = خطأ
        تفريغ = صحيح 
    أو تسلم إشارة من ضغط زر.يساوي :
        العدد.الثاني = الشاشة : نصه ( )
        العدد.الثاني = كعدد ( العدد.الثاني )

        إذا العملية = "+" :
            النتيجة = العدد.الأول + العدد.الثاني
            النتيجة = كنص ( النتيجة )
            الشاشة : حدد.النص ( النتيجة )
            العملية = ""
            تفريغ = صحيح 
        تم
    أو تسلم إشارة من ضغط زر.الفاصلة.العشرية :
        إذا كتبنا.فاصلة.عشرية = خطأ :
            الشاشة : الحق.نص ( "." )
            كتبنا.فاصلة.عشرية = صحيح
        تم
    أو تسلم إشارة من ضغط زر1 :
        إذا تفريغ = صحيح :
            الشاشة : حدد.النص ( "" ) 
            تفريغ = خطأ 
        تم
        الشاشة : الحق.نص ( "1" )
    أو تسلم إشارة من ضغط زر2 :
       ...باقي الأرقام مثلها مثل 1
    تم
تابع
الموضوع بسيط جداً:
1- في نهاية ضغط زر الجمع أو زر يساوي نقوم بتحديد قيمة تفريغ لتكون صحيح.
2- في أزرار الأرقام نتأكد من قيمة ذلك المتغير، فإن كانت صحيح نقوم بمسح الشاشة قبل عرض الرقم المكافيء للزر

يبقى شيء واحد هو تعميم العمليات لتشمل الطرح والقسمة والضرب. سوف نعرض هنا البرنامج كاملاً بعد إضافة هذا الجزء:
دالة صنع.زر(س، ص، العرض، الارتفاع، النص، النافذة):
    ز = زر جديد
    ز : حدد.المكان ( س ، ص )
    ز : حدد.الحجم ( العرض ، الارتفاع )
    ز : حدد.النص ( النص )
    النافذة : اضف ( ز )
    ارجع ب: ز
نهاية

ن = النافذة.الحالية ( )
زر1 = صنع.زر (40 ، 130 ، 30 ، 30 ، "1" ، ن)
زر2 = صنع.زر (70 ، 130 ، 30 ، 30 ، "2" ، ن)
زر3 = صنع.زر (00 ، 130 ، 30 ، 30 ، "3" ، ن)
زر4 = صنع.زر (40 ، 100 ، 30 ، 30 ، "4" ، ن)
زر5 = صنع.زر (70 ، 100 ، 30 ، 30 ، "5" ، ن)
زر6 = صنع.زر (100، 100 ، 30 ، 30 ، "6" ، ن)
زر7 = صنع.زر (40 ، 70  ، 30 ، 30 ، "7" ، ن)
زر8 = صنع.زر (70 ، 70  ، 30 ، 30 ، "8" ، ن)
زر9 = صنع.زر (100، 70  ، 30 ، 30 ، "9" ، ن)
زر0 = صنع.زر (70 ، 160 ، 30 ، 30 ، "0" ، ن)

زر.الجمع = صنع.زر (10،  70 ، 30 ، 30 ، "+" ، ن)
زر.الطرح = صنع.زر (10، 100 ، 30 ، 30 ، "-" ، ن)
زر.الضرب = صنع.زر (10، 130 ، 30 ، 30 ، "×" ، ن)
زر.القسمة = صنع.زر(10، 160 ، 30 ، 30 ، "÷" ، ن)
زر.يساوي = صنع.زر (40، 160 ، 30 ، 30 ، "=" ، ن)

زر.الفاصلة.العشرية = صنع.زر(100، 160، 30، 30، "."، ن)

الشاشة = سطر.نصي جديد
الشاشة : حدد.المكان ( 10 ، 30 )
الشاشة : حدد.الحجم ( 120 ، 30 )
الشاشة : حدد.النص ( "" )
ن : اضف ( الشاشة )

ن : حدد.الحجم ( 150 ، 210 )
ن : حدد.العنوان ( "الحاسبة" )
كتبنا.فاصلة.عشرية = خطأ
العملية = ""
العدد.الأول = لاشيء
تفريغ = خطأ

كرر :
    تخير :
    تسلم إشارة من ضغط زر.الجمع :
        العملية = "+"
        العدد.الأول = الشاشة : نصه ( )
        العدد.الأول = كعدد ( العدد.الأول )
        كتبنا.فاصلة.عشرية = خطأ
        تفريغ = صحيح
    أو تسلم إشارة من ضغط زر.الطرح :
        العملية = "-"
        العدد.الأول = الشاشة : نصه ( )
        العدد.الأول = كعدد ( العدد.الأول )
        كتبنا.فاصلة.عشرية = خطأ
        تفريغ = صحيح
    أو تسلم إشارة من ضغط زر.الضرب :
        العملية = "×"
        العدد.الأول = الشاشة : نصه ( )
        العدد.الأول = كعدد ( العدد.الأول )
        كتبنا.فاصلة.عشرية = خطأ
        تفريغ = صحيح
    أو تسلم إشارة من ضغط زر.القسمة :
        العملية = "÷"
        العدد.الأول = الشاشة : نصه ( )
        العدد.الأول = كعدد ( العدد.الأول )
        كتبنا.فاصلة.عشرية = خطأ
        تفريغ = صحيح
    أو تسلم إشارة من ضغط زر.يساوي :
        العدد.الثاني = الشاشة : نصه ( )
        العدد.الثاني = كعدد ( العدد.الثاني )
        النتيجة = لاشيء
        إذا العملية = "+" :
            النتيجة = العدد.الأول + العدد.الثاني
        وإلا إذا العملية = "-" :
            النتيجة = العدد.الأول - العدد.الثاني
        وإلا إذا العملية = "×" :
            النتيجة = العدد.الأول × العدد.الثاني
        وإلا إذا العملية = "÷" :
            النتيجة = العدد.الأول ÷ العدد.الثاني
        تم

        إذا ليس النتيجة = لاشيء :
            النتيجة = كنص ( النتيجة )
            الشاشة : حدد.النص ( النتيجة )
            العملية = ""
            تفريغ = صحيح
        تم
    أو تسلم إشارة من ضغط زر.الفاصلة.العشرية :
        إذا كتبنا.فاصلة.عشرية = خطأ :
            الشاشة : الحق.نص (".")
            كتبنا.فاصلة.عشرية = صحيح
        تم
--------
    أو تسلم إشارة من ضغط زر1 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("1")
--------
    أو تسلم إشارة من ضغط زر2 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("2")
--------
    أو تسلم إشارة من ضغط زر3 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("3")
--------
    أو تسلم إشارة من ضغط زر4 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("4")
--------
    أو تسلم إشارة من ضغط زر5 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("5")
--------
    أو تسلم إشارة من ضغط زر6 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("6")
--------
    أو تسلم إشارة من ضغط زر7 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("7")
--------
    أو تسلم إشارة من ضغط زر8 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("8")
--------
    أو تسلم إشارة من ضغط زر9 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("9")
--------
    أو تسلم إشارة من ضغط زر0 :
        إذا تفريغ :
            الشاشة : حدد.النص ("")
            تفريغ = خطأ
        تم
        الشاشة : الحق.نص ("0")
    تم
تابع
يبدو البرنامج طويلاً، لكن تذكر أنه كله أجزاء متكررة: الكود الخاصة بالعمليات مكررة أربع مرات والجزء الخاص بالأرقام عشر مرات! هناك بالتأكيد طرق لاختصار هذه الكود كما قلت، لكن حاليا...إنها تعمل :)


مازال هناك بعض الإمكانات التي يمكن إضافتها:
  • السماح بإدخال سلسلة مثل 12 / + / 13 / + / 15 بحيث تظهر نتيجة "12+13" عند ضغط علامة زائد الثانية قبل استمرار العمليات
  • إجراء العمليات بالترتيب الرياضي الصحيح، يعني لو أدخل المستخدم 7+5×2 تكون النتيجة 17 وليس 24
  • تدارك أخطاء المستخدم المحتملة
لكن هذه الإمكانيات خارج نطاق هذا المثال التوضيحي على أية حال. يمكنك أن تكتبها أنت إن أردت ^^