‏إظهار الرسائل ذات التسميات programming. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات programming. إظهار كافة الرسائل

الأحد، 23 ديسمبر 2012

حين تتحقق خطط المدى البعيد

حين كنت أعمل في صنع لغة كلمات سنة 2010 كانت هناك بعض القرارات التي اتخذتها في تصميم وتنفيذ اللغة. بعض هذه القرارات قد بدأت تظهر آثاره الآن!

الاثنين، 3 ديسمبر 2012

البوست عبارة عن كود

هذا مثال ورقة بارنسلي، من فرع من الرياضيات يسمى chaos theory، من المدهش حقاً الشكل المعقد الذي يمكن أن يظهر من هذه الكود البسيطة.

لتنفذ هذا البرنامج:
  1. حمل لغة كلمات من http://www.kalimat-lang.com
  2. قم بنسخ ولصق الكود بالكامل في محرر كلمات
  3. قم بتنفيذ البرنامج
س مشترك 
ص مشترك 
س = 0 
ص = 0 

علامة البداية 

ارسم.نقطة (س × 30 + 50، ص × 30 + 50)، 5 
الاختيار = عشوائي (100)
إذا الاختيار = 0 :
    تحويل1 ()
وإلا إذا الاختيار < 86 :
    تحويل2 ()
وإلا إذا الاختيار < 93 :
    تحويل3 ()
وإلا :
    تحويل4 ()
تم 
اذهب إلى البداية 

إجراء تحويل1 ():
    س = 0 
    ص = 0.16 × ص 
نهاية 

إجراء تحويل2 ():
    س = 0.85 × س + 0.04 × ص 
    ص = - 0.04 × س + 0.85 × ص + 1.6 
نهاية 


إجراء تحويل3 ():
    س = 0.2 × س - 0.26 × ص 
    ص = 0.23 × س + 0.22 × ص + 1.6 
نهاية 


إجراء تحويل4 ():
    س = - 0.15 × س + 0.28 × ص 
    ص = 0.26 × س + 0.24 × ص + 0.44 
نهاية

الأحد، 18 نوفمبر 2012

عن كون كلمات لغة للأطفال، ولماذا لا تكون لغة احترافية

هناك أكثر من شخص تحدث معي عن سبب إصراري أن تكون لغة كلمات لغة تعليمية وليست لغة لعمل برامج احترافية مثلها مثل Java, Python, ...الخ.

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

من الأسباب التي تدعو لجعل كلمات لغة احترافية:

  1. قد يكون هناك عائقاً نفسياً يمنع البعض من استخدام لغة للأطفال أو المبتدئين.
  2. ماذا سيفعل الأطفال (أو الكبار المبتدئين) بعد تعلم كلمات إن أرادوا عمل برامج احترافية؟
  3. ماذا عن حلم البرمجة باللغة العربية في كل مكان؟

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

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

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

الرأي الخاص بي: لماذا لم أجعلها كذلك

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

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

وهذا ما لا أستطيع أن أقوم به حالياً. ما أستطيع أن أقوم به هو تطوير اللغة نفسها، وهو ليس أمراً سهلاً حتى للغة مبتدئين.

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

الجزء الأخير: الخطوات المطلوبة لتكون كلمات احترافية

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

أولاً: كلمات في صورتها الحالية لغة قوية جداً. فيها مثلاً هذه الإمكانيات:
  • tail call elimination
  • destructuring
  • lambda expressions - في الإصدارة القادمة
  •  green threads
  • CSP channels
وهي إمكانيات معظمها لا يوجد في ++C، ولا بايثون، ولا جافا. (في حالات معينة مثل CSP  يمكن تطعيم تلك اللغات بمكتبات خارجية لتقديم هذه الإمكانيات، لكن في حالات مثل tail calls لا يمكن).

لكن على الجانب الآخر، اللغات الأخرى تقدم تنفيذا سريعاً للبرامج، تقدم garbage collection متقدم عن كلمات (ماعدا ++C التي لا تحب مثل هذه الرفاهيات)، تقدم مكتبات لأي شيء تريده، تقدم ضماناً معقولاً لخلو المترجم والآلة الافتراضية من الأخطاء، وتقدم خاصية استدعاء دوال خارجية [بايثون تقدم ctypes لاستدعاء إجراءات مكتوبة بالسي، جافا تقدم JNI لنفس السبب، سي شارب تقدم P/Invoke، وهكذا).

كلمات تحتاج إذاً، لكي تكون أقرب للاحترافية:
  • تطوير الآلة الافتراضية الخاصة بها (وهي من تصميمي واسمها SmallVM) لتكون أسرع وبجامع مهملات أفضل. أو كتابة نسخة من كلمات تعمل على ألة افتراضية موجودة.
  • ضبط إمكانية FFI الخاصة بها (وهي الخاصية التي تكافيء JNI/ctypes المذكورة بأعلاه). الخاصية موجودة بالفعل في كلمات لكنها تحتاج لاستكمالها.
  • إصلاح الكثير من الثغرات والنواقص الموجودة
  • صنع خاصية multiplexing over threads، ولو تم صنع هذه الخاصية فستكون ميزة نادرة لكلمات، لا توجد إلا في لغات مثل Google Go أو Erlang
  • صنع بعض المكتبات الأساسية مثل web, database, networking
  • عمل كل هذا بدون التأثير على سهولة تعلم اللغة، أو ملاءمتها للأطفال، أو جمالها [ربما يتطلب هذا فصل اللغة إلى لغتين واحدة للاطفال والأخرى احترافية، لكن بنفس الـsyntax تقريباً ونفس المكتبات].
بعض هذه الإمكانيات يجري العمل فيه فعلاً (مثلاً أعمل حالياً في خاصية multiplexing)، والبعض مؤجل للمدى الطويل، والبعض لا أدري إن كنت سأقوم به فعلاً أم لا. من يعلم؟ هؤلاء الذين يطلبون لغة احترافية، ربما يحصلون عليها ذات يوم.

الجمعة، 16 نوفمبر 2012

Solving an ACM problem with Kalimat (part 2)

  • هذا المقال تكملة للجزء الأول الذي تجده هنا، لكن في الواقع الجزء الثاني يتضمن كل المعلومات المطلوبة ولا تحتاج لقراءة الجزء الأول لتفهمه.
  • مسألة الـACM نفسها هنا
 ما المطلوب من المسألة؟ كتابة برنامج به وصف لمجموعة من المبان، وحذف الخطوط المتقاطعة بحيث يظهر فقط المحيط العام لتلك المبان، كما توضح الصورة:


كيف نحل هذه المسألة؟ من حسن الحظ أن شرح السؤال نفسه يلمح لنا بالحل!
The skyline vector should represent the "path" taken, for example, by a bug starting at the minimum x-coordinate and traveling horizontally and vertically over all the lines that define the skyline.

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

في البداية ستسير النملة أفقياً حتى تصطدم بجدار بمبنى:
فإن وجدت المبنى ستبدأ في التحرك رأسياً لتتسلقه


إن وجدت نفسها عند سفح مبنى من جديد، فستبدأ في تسلقه، وإن وجدت نفسها عند هضبة فستنزل

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

وكيف تنتقل بين الحالات؟

إن كانت واقفة على الأرض:
  • تسير إلى سفح أول مبنى أمامها

إن كانت واقفة على سطح مبنى:

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


إن كانت عند سفح:
  • تصعد لأعلى المبنى، ثم تكون حالتها "على سطح مبنى"
إن كانت عند هضبة:
  • إن كان هناك سطح مبنى يعوق هبوطها، تنزل إلى سطح ذلك المبنى ثم تصبح حالتها "على سطح مبنى"
  • إن لم يكن هناك عائق تنزل إلى الأرض (ص = 0) وتصبح حالتها "على الأرض"



الملخص:

لم يبق سوى كتابة الكود التي تمثل هذا الرسم، ثم نستطيع جميعنا أن نعود إلى البيت ونأكل الساندوتشات التي أعدتها أمهاتنا :)


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

الآن إلى الكوووود!!


كما نعلم، مجموعة البيانات المدخلة هي مصفوفة من ثلاثيات، مثل [[12، 10، 20]، [15، 8، 22]، [20، 12، 30]]، وكل ثلاثية تعبر عن مبنى [الحافة اليسرى، الارتفاع، الحافة اليمنى]. فلنبدأ بشيء بسيط: دوال قصيرة لاستخراج بيانات كل مبنى مما يجعل البرنامج أسهل في القراءة:
دالة يسار ( مبنى ) :
    ارجع ب: مبنى [ 1 ] 
نهاية 

دالة سطح ( مبنى ) :
    ارجع ب: مبنى [ 2 ] 
نهاية 

دالة يمين ( مبنى ) :
    ارجع ب: مبنى [ 3 ] 
نهاية

الآن نرى الإجراء الأساسي لحل المسألة:
بداية.البحث مشترك 

إجراء إجابة ( صف.المباني ) :
    بداية.البحث = 1 
    على.الأرض ( 0 ، 0 ، صف.المباني ) 
نهاية 

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

ماذا أخذ الإجراء على.الأرض؟ أخذ قيم س، ص، ومصفوفة المباني.

جميل جداً. الآن ننظر للإجراء نفسه:

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

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

ما معنى وكل إلى؟ انها تجعل السطر من "استدعاء إجراء" إلى "توكيل لإجراء". ما الفرق بينهما؟ في حالة التوكيل فإنه قبل استدعاء عند.سفح(...) سوف يتم أولاً حذف الstack frame الخاصة بـ على.الأرض( ) من الذاكرة، وهذا  طبيعي لأن هذا الجزء من البرنامج لا نحتاج أن نرجع إليه.

الآن نرى عند.سفح:
إجراء عند.سفح ( س ، ص ، مبنى ، المباني ) :

    ص = سطح ( مبنى ) 
    اطبع ص 
    وكل إلى عند.سطح ( س ، ص ، مبنى ، المباني ) 
نهاية 

إذا كانت النملة عند سفح مبنى، فإنها تتسلقه (بتغيير قيمة ص وطباعتها)، ثم توكل سائر العمل إلى الحالة الجديدة: عند.سطح

سهلة دي مش كدة؟

إجراء عند.سطح(س، ص، مبنى، المباني) :

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

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

لو كنت لاتزال تجد صعوبة، انظر إلى الصور مرة أخرى.

الآن نصل إلى عند.هضبة:
إجراء عند.هضبة(س، ص، مبنى، المباني) :

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

مرة أخرى: الأمر أبسط مما يبدو عليه. الدالة جزءان:

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

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

لو كان هناك قيمة للمتغير أعلى.عقبة، فهناك إذاً عقبة أمام نزولنا. بدلاً من النزول للأرض ننزل إلى سطح تلك العقبة (المبنى) ونغير الحالة.

أخيراً هذا هو الإجراء حدث.بداية.البحث
إجراء حدث.بداية.البحث (س، المباني) :
    
    لكل أ من بداية.البحث إلى عدد( المباني ) :
        إذا يسار (المباني [أ]) > س :
            بداية.البحث = أ 
            اذهب إلى النهاية 
        تم 
    تابع 
    علامة النهاية 
نهاية

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

هل يعمل البرنامج؟ القيم المطبوعة هي نفس النتيجة المكتوبة في موقع المسألة (ولكني لم أختبره على مدخلات أخرى)
يمكنك أن تختبره أنت إن أردت! الكود كاملةً تجدها هنا:
-- هذا البرنامج حل لمسألة Skyline problem من مسائل الـACM
 -- تجد المسألة هنا: http://uva.onlinejudge.org/external/1/105.html
 
-- اختبارات()
 حل.المسألة ( ) 

إجراء حل.المسألة ( ) :
    صف.المباني = [ ] 
    ملف.المدخلات = افتح.ملف ( "input.txt" ) 
    كرر مادام ليس ملف.المدخلات : منته ( ) :
        س = ملف.المدخلات : اقرأ.سطر ( ) 
        الثلاثية = تفصيص ( س ، " " ) 
        الثلاثية [ 1 ] = كعدد ( الثلاثية [ 1 ] ) 
        الثلاثية [ 2 ] = كعدد ( الثلاثية [ 2 ] ) 
        الثلاثية [ 3 ] = كعدد ( الثلاثية [ 3 ] ) 
        صف.المباني = صف.المباني + [ الثلاثية ] 
    تابع 
    اغلق.ملف ( ملف.المدخلات ) 
    إجابة ( صف.المباني ) 
نهاية 


بداية.البحث مشترك 

إجراء إجابة ( صف.المباني ) :
    بداية.البحث = 1 
    على.الأرض ( 0 ، 0 ، صف.المباني ) 
نهاية 


بداية.البحث مشترك 
إجراء على.الأرض ( س ، ص ، المباني ) :

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

 ص = سطح ( مبنى ) 
    اطبع ص 
    وكل إلى عند.سطح ( س ، ص ، مبنى ، المباني ) 
نهاية 

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

إجراء عند.هضبة ( س ، ص ، مبنى ، المباني ) :

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

إجراء حدث.بداية.البحث ( س ، المباني ) :
    
    لكل أ من بداية.البحث إلى عدد ( المباني ) :
        إذا يسار ( المباني [ أ ] ) > س :
            بداية.البحث = أ 
            اذهب إلى النهاية 
        تم 
    تابع 
    علامة النهاية 
نهاية 


دالة يسار ( مبنى ) :
    ارجع ب: مبنى [ 1 ] 
نهاية 

دالة سطح ( مبنى ) :
    ارجع ب: مبنى [ 2 ] 
نهاية 

دالة يمين ( مبنى ) :
    ارجع ب: مبنى [ 3 ] 
نهاية

الخميس، 6 سبتمبر 2012

حاجات مطلوبة عشان تفكر

قبل أن تفكر، تحتاج أن تعرف كيف ترى، وكيف تسأل أسئلة، وكيف تصف.

كيف ترى

أنت لا ترى بعينيك فقط. أنت ترى بعقلك. هذه نقطة بالغة الأهمية. العالم من وجهة نظرك غير العالم من وجهة نظري، وهما يختلفان عن العالم من وجهة نظر القطة في الشارع؛ مع أنه - مادياً - هو نفس العالم.

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

والمفاهيم التي تعرفها هي أعين جديدة ترى بها. في رحلتي في علم لغات البرمجة تعلمت فكرة الـcontinuation. منذ ذلك الوقت وأنا أراه في كل مكان: في أشياء برمجية سابقة، في الحياة عموماً، في أفكار تكنولوجية غير برمجية. شيء شبيه بذلك حين قرأت عن الـmonads.

ونظرية Piaget في التطور المعرفي للأطفال! النظرية تتحدث عن الـconstructivism، منذ أن قرأت عنها وأنا أنظر في كل شيء فأراها..
  • لا يكفي نقل التكنولوجيا لننهض علميا؛ لابد من بناء التكنولوجيا، وإلا سنسير في حلقة لا تنتهي من "غيرنا يبتكر، نحن ننقل".
  • عند شرح كود موجودة لأحد نحن غالباً ما نشرح الكود في أحدث صورها، لكن هناك معلومات قيمة عن الكود تأتي من تاريخها (من بنائها). لماذا اتخذت قرار كذا ولم أتخذ كذا؟ لماذا هذه الفصيلة موجودة بهذه الطريقة؟ هذه النقاط تأتي من خبرة ومن تجارب في إصدارات قديمة من البرنامج، وإني لأتخيل IDE بها طريقة لتأريخ المراحل المهمة في حياة هذا البرنامج.
  • التاريخ نفسه! إن أردنا أن نخرج مما نحن فيه علينا أن نفهم أولاً كيف قد صرنا فيه! ليس فقط بجمل مختصرة على غرار "لقد صرنا متفرقين"، بل أيضاً بتفاصيل. كيف صرنا كذلك؟ متى بدأ هذا؟ وكيف استمر؟ وماذا أيضاً غير التفرق؟ وماذا كانت العوامل الداخلية؟ وماذا عن الخارجية؟ هل نستطيع رسم خط زمن لمراحل "التخلف" والأسباب الأساسية لكل مرحلة؟
  • كيف نغير القيم الموجودة في المجتمع حالياً؟ فلنفهم كيف بُنيت هذه القيم!

(ليست هذه التدوينة عن نظرية Piaget، تذكر: نحن في جزء "كيف ترى"، أتحدث عن كيف تغير الأفكار في عقلك من نظرتك للعالم. منذ عرفت النظرية وأنا أنظر لكل المجالات الأخرى نظرة بنائية).

وكيف تسأل أسئلة؟

Computers are useless. They can only give you answers.
-- Pablo Picasso

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

"إنتاج أفريقيا هو (أ) 8% (ب) 9% (ج) 11% (د) 13% من إنتاج الحديد العالمي".
"What is the difference between x++ and ++x"
"لما بترجع البيت بتعلق هدومك والا بترميها" (هذا سؤال حقيقي أخذته في interview)

هي دي الأسئلة؟؟؟

كان هناك قديماً خمس مسلّمات للهندسة منذ أيام إقليدس، وكان كثير من العلماء الرياضيين يعتبرون المسلّمة الخامسة زائدة (أي يمكن إثباتها من الأربعة السابقين لها، وبالتالي لا داع لاعتبارها مسلّمة بل هي نظرية عادية). وقد حاول العلماء لمئات السنين، علماء الحضارة اليونانية ثم الإسلامية ثم الأوروبية، أن يأتوا بذلك الإثبات ولم يقدروا.

ثم جاء كارل فريدريك جاوس في 1817 وسأل نفسه: ماذا يحدث لو افترضت أن المسلّمة الخامسة ليست بالضرورة صحيحة؟ والتفكير في هذا الأمر دفع بسؤال آخر: ماذا لو اخترعت "هندسة" جديدة بالأربع مسلّمات + خامسة مختلفة عن المعتاد؟

هذا الأمر قد فتح الباب لعلوم الهندسة غير الإقليدية non-Euclidean geometry: هندسة يمكن أن تتلاقى فيها خطوط متوازية، أو هندسة على سطوح غير مستوية (أفادت في الجغرافياً، من ضمن ما أفادت)، أو بنظام إحداثيات منحني (وقد استفاد آينشتاين كثيراً من هذا الأمر حين وضع نظرية أن الجاذبية هي انحناء الزمكان).

أبواب جديدة من العلم، جاءت من السؤال المناسب..

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

العلم الحديث مبني على التجربة. كيف تسجل ملاحظات تلك التجربة؟

تخيل علم الرياضيات الحديث لو كنا مازلنا نستخدم الأرقام الرومانية. بسرعة: اجمع XI على XXV. مجرد تغيير طريقة وصف الأرقام غير من تفكيرنا فيها.

وكيف تصف المجتمع حين تريد تغييراً سياسياً؟ وكيف تصف مشروعك للآخرين؟ وكيف تصف المشكلة التي تريد أن تحلها؟

وكيف يكون شكل برامجنا لو تخلينا عن فكرة "البرنامج في ملفات نحررها بمحرر نصي"؟ وما البدائل لوصف المطلوب من البرنامج؟

كيف تصف الألوان لشخص أعمى؟ وكيف تصف الروائح في فيلم رسوم متحركة؟ وكيف تصف ملمس معين في صورة؟

ملمس في صورة؟ قرأت في طفولتي مقالاً عن قصر الحمراء بغرناطة، يقول أن الزخارف متنوعة ومصنوعة بطريقة كأن العين "تتحسسها"..انظر للصورة واحكم بنفسك:

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

كيف تصف، هذا مهم.

الجمعة، 29 يونيو 2012

ابحث عن الفكرة الكبيرة!

كنت أريد أن أعلم الفرقة الأولى شيئاً عن البرمجة الشيئية (OOP).

في المحاضرة الأولى لم اتطرق للـclasses اصلاً، بل كان كلامي عن الـobjects. في ذلك اليوم تعلم الطلبة ان البرنامج مكون من "كائنات" أو "أشياء"، وأن هذه الأشياء تعبر عن اجزاء مختلفة من البرنامج مثل أزرار، موظفين، أو حتى algorithms متنوعة، وأن الأشياء تتعامل مع بعضها عن طريق ارسال رسائل لبعضها البعض، ووسيلة تنفيذ الرسالة اسمها method، وكل كائن مسؤول عن الاستجابة بطريقته.

هذه هي الفكرة الكبيرة للبرمجة بالأشياء: البرنامج مكون من أشياء، وهي تتبادل الرسائل! كل شيء آخر عبارة عن تفاصيل. هناك لغات شيئية لا يوجد بها inheritance، ولا حتى classes، مثل JavaScript أو Self.

ماذا عن الديموقراطية؟ بالنسبة لي الفكرة الكبيرة هي "انتزاع السلطة من القلة وإعطاؤها للكثرة". ربما يكون هذا بصورة انتخابات، أو بشيء مثل الديموقراطية التشاركية، أو بتمكين المجتمع المدني، لكن الفكرة الكبيرة ليست في هذه التفاصيل.

أنا لست خبيراً سياسياً، وهذا الرأي رأي شخصي، لكن حتى لو فكرتي الكبيرة خاطئة، فهناك حتماً فكرة كبيرة أخرى!

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

ماذا عن الفكرة الكبيرة وراء البرمجة؟ يقول David Harel هذا الملخص:

Programming is not about doing; it's about causing the doing

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

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

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

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

الفصل الأول: أنواع البيانات

عدد صحيح / Integer / من -2,147,483,648 إلى 2,147,483,647
قيمة منطقية / Boolean / تأخذ true أو false
قيمة احادية الدقة / Single / ...

هذه ليست البرمجة!

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

ونرجع لأول محاضرة قدمتها في تدريب OOP: بدأت بنماذج لبرامج شهيرة (MS Word, Paint, Age of Empires). ما هي الكائنات في مثل هذه البرامج؟ كيف تتفاعل؟

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

البرمجة، وقوالب الطوب، والحلم المختفي

لماذا أحب الكمبيوتر؟ في الثمانينات وانا في المدرسة رأيت برنامجاً للرسم يعمل على الكمبيوتر المنزلي. لا اعرف نوع الجهاز تحديداً لكن اعتقد أنه BBC Micro. كانت الأجهزة في تلك الفترة متقاربة على أي حال.

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

لقد كانت لحظة فارقة في حياتي. انا اعتبر نفسي إنساناً مبدعاً لكني كسول؛ والآن هناك آلة تقوم بالعمل الممل وتترك لي العمل الإبداعي! هذا يغير أشياء كثيرة. ولهذا أحببت الكمبيوتر.

هل تعرف ما هي إمكانات جهاز BBC Micro؟ إن سرعته هي 2 ميجاهرتز (وليس جيجا). الذاكرة من 32 كيلوبايت، والمعالج 8 بت.

ثم ننظر لهذا النظام (Sketchpad) وهو موضوع رسالة الدكتوراة للباحث Ivan Sutherland في الستينات.



النظام ليس فقط مبهر بالنسبة للفترة التي ظهر فيها، إنه مبهر حتى الآن! الشيء الذي يهمني في هذا المثال هو انه يستغل إمكانات الكمبيوتر الحسابية ليقوم بكثير من العمل بدلاً من الإنسان: هل تريد هذه الخطوط متوازية؟ هل تريدها متعامدة؟ هل تريد هذه النقاط على استقامة واحدة؟ فقط اطلب هذا من الحاسوب!

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

ننظر أيضاً لبرامج الرسم؛ سأركز على البرامج 2D حالياً: برنامج مثل Inkscape يسمح بعمل تدرجات للألوان، ويسمح باستخدام منحنيات بيزييه، ويسمح بأن تكون الخطوط مثل قلم حبر أو رصاص أو فرشاة. ويسمح بعمل أشكال ثلاثية الأبعاد. لكنه لا يساعدني أن أرسم!

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

لماذا لا تساعدني أيها الحاسوب؟؟

ثم ننظر للبرمجة. لماذا لا يساعدني الكمبيوتر؟ إنه يعطيني محرراً أكتب فيه، ثم يسكت! على الأقل أدوات مثل Eclipse هي خطوة في الاتجاه الصحيح. هب أنني غيرت عدد الـparameters في دالة. يقوم Eclipse وقتها بتنبيهي إلى كل أماكن استدعاء الدالة لكي اضيف فيها الـparameter الإضافي. ولو كانت الدالة معرفة في class، فهو يقوم بتنبيهي لكل فصيلة فرعية تعيد تعريف الدالة لكي أغيرها أيضاً..

هكذا يكون الكمبيوتر الشاطر: يقوم بكل عمليات البحث والمطابقة - تلك العمليات المملة - لكي لا احتاج أنا الإنسان أن اقوم بها.

(الظريف ان بعض المبرمجين يتباهون بعدم احتياجهم لمثل هذه الأدوات.)

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

إن أجهزة الكمبيوتر الموجودة في الثمانينات كانت إمكاناتها لا تذكر مقارنةً بالأجهزة الحديثة، لكن البرامج القديمة، كثيراً ما أشعر انها كانت "ألذ" بكثير. لقد تغيرت نظرة المبرمجين للعلاقة بين الكمبيوتر وصاحبه؛ قديماً كان هناك تركيز كبير على فكرة "الكمبيوتر يقوم بالأشياء المملة لكي يقوم الإنسان بالأجزاء المهمة"، الآن يبدو وكأن الشخص هو خادم الكمبيوتر وليس العكس: تحديث الويندوز، الكشف عن الفيروسات، تركيب SVN/IDE/JVM/Maven....الخ قبل أن تبدأ البرمجة.

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

وعموماً مازال هناك البعض يحمل الفكرة: مثلاً برنامج Scrivener هو منسق للكلمات يساعدك فعلاً على تنظيم أفكارك وليس مجرد تغيير شكل الخطوط وأحجامها. برنامج Sketchup يساعد بالفعل على التعبير عن افكارك بطريقة رسومية بسرعة. هناك جيل جديد من الأدوات البرمجية يحاول ان يقوم بالأشياء "المملة" بدلاً من المبرمج.

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

أعتقد أن جزءاً من سبب المشكلة قد يكون التفريق بين "المطور" و"المستخدم". لقد تعلمنا في الجامعة أن هندسة البرمجيات تبدأ بجمع متطلبات البرنامج requirement analysis وتنتهي بصيانة البرنامج. لكن في الستينات، السبعينات، الثمانينات، كان كثيراً ما يكون المطور والمستخدم هما نفس الشيء. كان الإنسان يبرمج لنفسه أولاً.

الأربعاء، 25 أبريل 2012

شوف اللي ينفعك

كيف اذاكر؟ كيف اقرأ؟ كيف أتعلم؟
هل اعمل في الاكاديميا ام القطاع الخاص؟
هل اتخصص في مجال معين واحترفه، ام اعرف في كل شيء؟

توجد ردود تقليدية على هذه الأمور. مثلاً الرد التقليدي في موضوع المذاكرة يكون شيء مثل الآتي:

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

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

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

إنه التنوع يا سادة

لكن الناصحون ينسون كلمة اسمها diversity. ليس كل الناس يفكرون بنفس الطريقة (ليس لديهم نفس الsoftware على رأي التفكير الحوسبي)، وليست كل البيئات مثل بعضها. القطاع الخاص في Microsoft غير Google غير Makesense. الاكاديميا في MIT غير جامعة النيل. هناك اهداف في الحياة تحتاج لتخصص واهداف يضرها التخصص.

وانا مختلف عن الصورة التي يتوقعها الناس (كفى اتهاماً لي بالاستعلاء، "مختلف" غير "افضل"). ربما جزء من رسالتي في الحياة ان انبه الناس لموضوع الـdiversity هذا.. مهلاً يا أخي وانت تنصح! نصيحتك غالباً لن تنطبق علي! فكر في الظروف قبل ان تتكلم!

حتة نرجسية برمجية

كيف ابرمج؟ حين كنت اعمل في لغة كلمات كانت طريقتي هي اربع ايام من التفكير ويوم من التكويد. اما التفكير فكان يجري في دماغي بينما الف وادور في البيت: لا استخدم UML، لا diagrams، لا شيء. ثم حين اكود يكون الحل شبه محدد في دماغي فاجد الكود تكتب نفسها إلا في مواقف معينة يكون الحل المفترض مخالفاً للواقع العملي؛ وقتها نعود لمرحلة التفكير.

لكن من عدم الحكمة ان اصنع من هذه الطريقة methodology جديدة اسميها اسماً خلاباً - مثلاً طريقة 4+1 ، واسوقها على انها الحل النموذجي للمشاريع البرمجية مثل الـagile وما سبقها..الطريقة ببساطة نفعت معي في مشروع معين. لا يوجد اي سبب علمي لأن اقول انها ستنفع لو تعممت. هي بالتأكيد تنفع مع آخرين، لكن مع الآخرين؟ هذا أمر مختلف.

أين الأساس العلمي لهذه النصائح؟

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

وددت لو كان اصحاب كتب التنمية البشرية اياها يقدمون مراجعاً عن مصادر النصائح المذكورة في كتبهم. لابد لمؤلفي هذه الكتب ان يعاملوا القاريء على قدم المساواة. حتى لو تريد تبسيط المعلومات للقاريء العادي، لماذا لا تترك ملاحق/هوامش تقول "هذا مبني على نظرية فلان للعالم فلان المنشورة سنة كذا في كتاب كذا"؟؟

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

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

عودة إلى النرجسية

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

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

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

تخصص ام لا تخصص؟

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

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

او تخيل التفكير الحوسبي مثلاً. إن كان هناك عكس لكلمة "تخصص" فهو غالباً هذا.

هل معنى هذا انه لا فائدة من النصح؟

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

بعد كل ما قلته - صدق او لا تصدق - انا مؤمن انه هناك مفاهيم ثابتة يمكن النصح بها :)

مثلاً: اهم نصيحة اقولها لمن يذاكر هي انك لم تذاكر حقاً بمجرد انك شعرت بالفهم؛ لابد من موقف اختبار تتأكد فيه انك فهمت حقاً. لو كانت المادة نظرية فلابد من حل اسئلة والتأكد من انك كتبت الحل الصحيح. لو كانت المادة برمجية فاكتب كود عن الذي درسته ولا تترك الـIDE إلا والكود تعمل بصورة صحيحة. النفس خداعة جداً ولو قلت "انا خلاص فهمت" فـ 99.999% ان هذا ليس صحيحاً.

ايضاً المذاكرة أولاً بأول مهمة. في افضل فترات حياتي دراسياً (الفرقة الاولى بالكلية) كنت لا اترك الاسبوع يمر بدون (1) مذاكرة المحاضرات (2) حل الاسئلة. هذا جعل الحياة سهلة، والمذاكرة ليست هماً. كانت فترة طيبة في الحياة.

ايضا في موضوع التخصص..نصيحتي ان تجرب اشياء كثيرة حتى تعرف ما تحب وما لا تحب. لقد جربت الgraphics ثم game programming ثم AI حتى وصلت اخيراً لما احببت وهو علم لغات البرمجة programming language theory، وبعد ان ظننت نفسي استقررت فإذا بي اجد التفكير الحوسبي وعلم النفس التربوي..وهي امور مازلت احاول الدخول فيها إلا ان بعض من جوانبها مازال مرتبطاً بطريقة او بأخرى بلغات البرمجة وتصميمها.

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

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

الاثنين، 9 أبريل 2012

Where is the casual programming?

I did not learn to program to have a software development job. True story.

I learned it for two reasons: (1) To have an aid for thinking and expressing ideas. What Steve Jobs called "A bicycle for the mind". (2) To automate repetitive tasks. Unfortunately, I don't seem to be doing much of either.

Perhaps some people are doing more than me. The Unix/Linux fans - some of them - write adhoc shell scripts or one-liners to solve casual problems. Perl and Python were created for such tasks. I suppose I could be complaining of a non-problem, except it is a problem. Programming is not casual enough.

The first barrier to casual programming is that you've got to learn too much stuff (too much to call it casual). This is the first and only shell script I wrote:

#!/bin/bash
cp -R Program ProgramCopy
cd ProgramCopy
find . -name bin -exec rm -rf '{}' \;
find . -name obj -exec rm -rf '{}' \;
zip -r ../Program`date +%d%B%y`.zip * -x \*~
cd ..
rm -rf ProgramCopy

It takes a program directory, removes temporary compiler generated files, and puts the code in a zip file with today's date. I made it with by trial, error, and Googling. It made me not want to write shell scripts again; feels too much like piecing together jigsaw puzzles where you first have to know which pieces actually exist.

Would I read a book about shell scripting? Nope. It's too much of a hassle for solving only one bit of the casual programming problem. Wouldn't help me much with writing a quick GUI or Web app to solve the problem, or to pull some data from Excel and write them into a .pdf

So how about Python? It has lots of libraries to do all of that and more. The problem is twofold:
1- The user needs to find the required libraries.
2- The user needs to read the documentation of those libraries.
3- The user usually does this with little less than an editor and an open browser tab.

That's the real problem with dynamic typing: With Java, C# and C++ I learn APIs on the go. I use autocomplete and when in doubt I point to the function invocation and press F1 to read the manual entry about this function. If I feel I need more background information, I follow the links higher in the doc hierarchy and begin learning about the big picture the exact moment I realize I need to learn this stuff.

I always wonder how Lisp and Python fans go along. They actually remember the difference between mapcar, mapcan, mapc...maybe I'm stupid or something.

But with the big three static languages, I have another problem: The IDEs take toooo long to load. If I need to write a utility to rename files in a certain way; I don't think "sure, I'll fire Eclipse, create a new Java project in the workspace, create a new run entry, & write and test the code".

Visual Studio? Qt Creator? the same.

What else? I wish everything had an easy to access API. If I can do it as a user, I want my code to do it. You know those cool hacks where people program small robot cars to bring them coffee? They should be trivial to write. I want to write a utility to, say, extract my old blog posts and find all posts written in Arabic, and tag them with "arabic-posts", and I want it running in a time comparable to what it took to describe it.

func isArabic(str)
...
end
blogger.blog("iamsamy", pw="*****").posts.contents.filter(isArabic).tag("arabic-posts")


You know what? Maybe there's a library that actually does this; but I need to find a "gem" or "egg" or "crate" or whatever to do it. And I need to read the docs. And the library may be out of date. And I'd be writing this in a command line window or an editor without autocomplete. And when I have a different casual, trivial, task, I'll need to do so all again.

Oh man. And I'm a professional and experienced programmer. How about the grocer or pharmacist or school student? We need things to be better!

Ok, we can start with a decent language with excellent library support (or we can develop a new one if we feel we have too much time on our hands). Maybe Rebol or Python or Ruby; they seem to be created by people who like to write code for solving casual problems.

If the language is dynamically typed, we could use some sort of technique to enable auto complete, like type inference or such. Otherwise use a fun but statically typed language, maybe C#.

Now we need an IDE that
  • Loads fast
  • Has very tight integration with a library repository, with a catalog of only the best libraries, easily searchable. I should type "blogger", find at most one or two working options, and press "add". I should be able to see the documentation before pressing add.
  • The documentation should have working examples for the top 10 casual tasks usually done with this library. If I'm lucky I'd press "copy this example", "run", and be done.
  • The IDE should have little cues in the code, like allowing me to select a directory from a dialog then use it as a file name in the File object's constructor, or choose a URL from my current browser tabs...etc
  • There should also be some form of API discoverability. I should search for "convert jpg" and find a class to do the task, even if the name doesn't neccessarily include "convert" or "jpg".
  • There should be a trivial to use GUI kit - like say Shoes - and a similar web kit.
I could go on and on....

الثلاثاء، 13 مارس 2012

سنوات قطر 3 - انا مبرمج يوجه نفسه بنفسه

(هذا المقال هو الجزء الثاني من جزئين)

انتهى الجزء الأول بأنني قد تعلمت البرمجة. ولكن كيف مارستها وطورت نفسي فيها؟

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

كما كانت الكتب متقدمة تكنولوجياً. هناك كتب تعلمك تركيب sensor ضوءي بالكمبيوتر وصنع برنامج إنذار لو مر شخص او شيء أمام الsensor. هناك كتاب في السلسلة عن البرمجة بالـmachine language...

نعم. لغة الآلة، للاطفال، في الثمانينات. هذا هو الكتاب على موقع امازون إن لم تصدقني، وإن المقابلة رهيبة بين الغلاف الطفولي الملون وبين عنوانه الذي يرتجف له الكثير من طلبة هندسة وحاسبات :]

وهناك من يشك حتى هذه اللحظة في موضوع تعليم الأطفال البرمجة. هأ!

المصدر الآخر كان الكتب التي نشرتها شركة العالمية (المسؤولة عن كمبيوتر صخر)..كنت اخذ امي لمحل الكمبيوتر كل فترة لتشتري لي نسخة. هذه صور الاغلفة من مقال سابق كتبته..

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

سلحفاة؟ لغة برمجة؟ ما الأمر؟ كان قد جاء مع كمبيوتر صخر كتالوج بكل البرامج التي صممتها "العالمية" له (وكانت كثيرة) منها صخر لوغو. وكانوا يرسمون في الكتالوج سلحفاة.

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

- ولكني أريده!

قالت أمي: هل أنت متأكد أنه سيفيدك؟

- نعم!

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

لم يكن برنامجا عادياً، كان دليل الاستخدام كثيفاً وليس بضع صفحات كالبرامج السابقة. وبدأت أقرأ. إن لغة Logo لها قصة فهي صممت اصلا للتعليم ومبنية على مباديء علمية حديثة اسمها constructionist learning وصممها خبير تعليمي اسمه Seymour Papert، وكانت لغة متطورة بها اشياء لم اكن احلم بها في الbasic:
- subroutine calls
- list data structures
- tail-call elimination
- سلحفاة

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

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



لكن مازالت "الوراثة" ظاهرة :)

جربت أيضا برمجة بعض الاجهزة الغريبة مثل Casio PB 1000، وهو يعتبر جد، جد، جد الPDAs أو الSmartphones الحديثة. كانت الشاشة اربع سطور..أربعة!! هذه صورته الأنيقة جداً. هلم وشاهدها قبل ان تحذفها الويكيبديا :]

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

strlen(s)
char *s;
{
int n=0;
while(*s++) n++;
return n;
}

ما هذا؟؟ هل هي رسالة بالشفرة؟ أين هذا من PRINT, FOR, NEXT؟ أين هذا حتى من اوامر صخر لوغو عالية المستوى مثل اقرأ.حرف أو كرر؟ لا تظنني جاهل في السي او غير معترف بأهميتها، لغة كلمات مكتوبة بالسي++، لكن الآن أعتقد أنك قد عرفت لماذا اللغة اسمها 'كلمات' وليس 'رموز'.

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

سنوات قطر 2 - انا مبرمج :)

هناك ثلاث مراحل للتطور الفكري في حياتي:
  • مرحلة الاهتمام بالنهضة والتاريخ وعلم الاجتماع...الخ، في 2008
  • مرحلة التعرف على الفرق بين البرمجة والcomputer science وانا طالب بالجامعة، وشغفي بالـ discrete math, logic...الخ
  • واهم مرحلة على الإطلاق: تعلمي البرمجة في الصغر والإعجاب بفكرة "المخترع". سنة 1987-1991 في سنوات قطر.

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


ولو اخترت البيسك فكان هذا ما سأراه:


وكنت انظر إلى الشاشة والسؤال الذي يخطر على بالي هو..."ماذا أفعل بهذا الشيء؟؟" اجرب ان اكتب حروفاً عشوائية ثم اخرج من البيسك واشغل الألعاب. كان لابد من خطوة اخرى...

المدرسة

كنت في مدرسة بريطانية اسمها Qatar international school، مازالت باقية حتى الآن بل ولها الآن موقع على الإنترنت (ربما عرفوا انني سأدون عنهم). كان المعلمون فيها اجانب إلا قليل من العرب، منهم معلمة الكمبيوتر المصرية. وكانت تعلمنا برمجة أو على الاقل تحاول.

كان الترم كله تقريبا كالآتي:
  1. تكتب هي البرنامج على السبورة.
  2. نكتبه نحن على الكمبيوتر.
  3. غير مسموح لنا ان نعلن اننا انتهينا إلا حين يعمل البرنامج ويعرض النتيجة الصحيحة.
  4. حين تظهر النتيجة الصحيحة، نقضي باقي الحصة في الالعاب على الاجهزة.
ما هي نوعية البرامج؟ كانت نوعان: برامج تعلمك قواعد لغة البيسك بالامثلة، مثل يبرنامج يستخدم امر PRINT بصيغه المتعددة، والنوع الثاني برامج ظريفة أو نافعة مثل برنامج جدول الضرب أو حوار قصير مع المستخدم.

بعد ذلك، ربما الترم الذي يليه - لا اذكر - بدأت المعلمة تقول: يا شباب، الم تلاحظوا في البرامج التي كتبتموها ازواج من الكلمات دائما تأتي مع بعضها؟ إن FOR دائما معها NEXT، بينما IF معها THEN...الم تلاحظوا؟

اعتقد ان هذه الطريقة جيدة جداً على عكس المتوقع. لماذا؟
  • لقد تدربنا تدريبا كاملا على استخدام لوحة المفاتيح حتى حفظت ايدينا PRINT, FOR,...الخ. عدم الكتابة الجيدة كانت عائقا امام الاطفال الذين جربت تعليمهم بكلمات.
  • كان العرض بالامثلة قبل الشرح، وقد رأينا ان البرمجة تعطي نتائج ظريفة مثل جدول الضرب.
  • كان لا يسمح بالالعاب قبل تشغيل البرنامج بصورة صحيحة، فتعلمنا اهمية كتابة كل حرف، رقم، فاصلة بشكل صحيح.
  • كان هناك العاب في الموضوع فلن يكتئب الاطفال كثيراً.
ما الذي جعل المعلمة تستخدم هذه الطريقة التي لا يوجد فيها شرح لمدة ترم كامل؟ لا اظن انها كانت مهملة مثلاً أو غير مهتمة - كانت تصرفاتها ليست تصرفات شخص هكذا..هناك احتمال:
- انها ترى هذه الطريقة هي الصحيحة من مصادر علمية أو تربوية.
- انها تراها الطريقة الصحيحة كاجتهاد شخصي منها.
- انها فعلت ذلك لأنها خافت ان ينفر الاطفال من البرمجة، فقررت ان تمشي بالتدريج جداً.

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

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

فأردّ: الا يمكن ان تلعب على جهاز آخر؟ أنا أريد أن أجرب شيئاً...

(لا تنس قراءة الجزء الثاني)

الأحد، 11 مارس 2012

الأجهزة الالكترونية المبرمجة وتطوير التعليم

تكلمت قبل ذلك عن تعليم الاطفال البرمجة والتفكير الحوسبي وتطوير المدارس بطرق ابداعية. الآن سأتكلم عن افكار مرتبطة بالhardware وليس مجرد البرمجة. كي لا يغضب عشاق الembedded systems أو هندسة ;)

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

المقال هذه المرة لم ابذل فيه مجهوداً كبيراً بقدر ما هو تجميع لمشاريع موجودة بالفعل...

الصانع الآلي (Makerbot)

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

فطيرة التوت (Raspberry Pi)

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

هناك فكرة ان الطالب ينبغي ألا يتعلم إلا البرامج التي سيعمل عليها حين يكبر (يعني excel, word...)..هذا تفكير قصير المدى؛ انت لا تعلّم الطفل كيف يقرأ البطاقة الضريبية...أنت تعلمه كيف يقرأ! ثم بعد ذلك يطبق معرفته على كل مجال موجود أو حتى لم يخترع بعد. اعتقد ان مثل هذا الجهاز خطوة جيدة في العودة لفكرة الكمبيوتر المنزلي المتاح للجميع. اعتقد ايضاً اننا ينبغي ان نبدأ بفكرة Raspberry ونطور فيها بشدة ولا نكتفي بالموجود! تخيل كمبيوترات رخيصة ذات كاميرا أو دوائر صوتية أو تشبيك WiFi أو...أو...

لا تفكر في الهاردوير فقط، بل الأهم أن تفكر في التطبيقات: بوجود هذه الدوائر ماذا سيتمكن الطفل المبدع أن يفعل؟ تخيل الطفل يمسك الكمبيوتر في يده كأنه مسدس (وهو كمبيوتر صغير ورخيص) ويستخدم الدائرة التليفزيونية ليراجع البرنامج تصويب الهدف على "الأعداء"...الآن تخيل هذه النوعية من اللعب وقد صممها الطفل بنفسه بوجود حاسوب رخيص بكاميرا + مكتبة معالجة صور قوية سهلة الاستخدام..

الأفكار في هذا المجال تكتب نفسها أصلاً...فقط تخيل!

حركات Kinect

نحن نعرف جهاز Kinect الذي يعمل على الX-box، ويرصد حركات يد، جسم، وجه...المستخدم ليتحكم بهم في اللعبة. الذي قد لا يعرفه الجميع هو انه هناك تيار لاستخدام الكينكت في التعليم التفاعلي وهذا موقعها.

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

البرمجة للأطفال مع الاجهزة: سكراتش.

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

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

س = سيارة جديد
س: اتصل.بالجهاز( )
س: تحرك.امام(5)
س: انعطف.يمين(18)

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

...ثم حين يكبرون يصممون السيارة التي تقود نفسها :)


خاتمة

لا أريد أن يكون هذا مجرد مقال، بل أريده نداءً: الوطن العربي لا يخلو من المبرمجين والمهندسين وهواة الالكترونيات والembedded systems ومطوري التعليم المبدعين..

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

الجمعة، 9 مارس 2012

All about pointers: part 2

So now you learned pointers from part 1, right? What can we now do with them?

Well, we can use pointers in two ways:
1- As an abstraction over variables.
2- As just a memory location.

Abstraction over variables

Normal variables let us abstract over values; meaning "do something with x whatever value it has". Well, pointers let us store variables in variables, so to speak, and thus abstract over them.

For example, there is no pass by reference in C, but we can emulate it with pointers:

void readInt(int *x) {
cin >> *x;
}
main() {
int t;
readInt(&t);
}

The function main is passing the location &t (by value) to readInt. When readInt modifies *x, this means "go to the address stored in x, and in that address, store whatever comes from cin >>". This modifies the value of t; which is what we wanted.

This pass-by-value works for anything that has a memory location; not just simple variables:

main() {
Point p;
readInt(&(p.x));
}

This will take the address where p.x is stored, and pass it to readInt; so it will be the address where readInt will write.

Is there another use of 'abstraction over variables' other than pass by reference? Well, this depends on your imagination. We can do things like this:

void getAge( ) {
int x = 8;
dialog.scrollBox1.setBinding(&x);
showDialog( );
cout << x;
}

Here we can imagine the setBinding function storing a pointer to an integer (pointing to x in the example) and whenever the user slides the scroll bar, the content of the address stored in the pointer is changed. Therefore after the showDialog function ends we find the value of x automatically reflecting the scroll bar position. It is as if we passed the variable itself as an argument to the setBinding function.

Pointers as memory locations

We can also treat a pointer as just a location in memory, not associated with a named variable that already exists. This is helpful in situations like:

1- Dynamic memory.
2- Reading and writing buffers.
3- Accessing hardware devices.

Dynamic memory:

Local variables in functions are automatic variables; the size needed for each function's vars is calculated at compile time and space for all vars is allocated at function call, deallocated at function exit. This is useful for most programs but sometimes we want full control of memory allocation at runtime:
- Perhaps we have an array with non-fixed size.
- Perhaps we're using a linked list; where memory must be allocated only when we need to add to the list.
- Perhaps we're creating an interpreter for our own programming language, where the user's program will allocate memory.

In all cases, memory allocation takes a form like this
myPointer = malloc(memSize);
or
myPointer = new type;
or
myPointer = new type[numElements];

...and I can access the content of the pointer normally with *myPointer = xyz;

We are here using the pointer to store the address of a hypothetical variable that wasn't declared in the code. A 'run-time' variable if we may say. And since they need not be declared at compile time we can have as many of them as we wish and at the time we wish.

I think this has a theoretical aspect; and relates to theory of computation: think of turing machine and the infinite tape that gives them their computational power; and of finite state automatons and the finiteness of their states, as if they were 'compile time' memory :)

anyway...

Reading and writing buffers

Think of the fread function in C:

main() {
Point p1;
fread(&p1,myFile, sizeof(Point));
}

Here the fread function doesn't care if it's reading a point or not: all it needs is a memory location and the number of bytes to read, and it will fill that memory with data from the file. Here the pointer is treated purely as an address.

Accessing hardware devices.

In the good old days of DOS, you could do stuff like this:

// note: just a sample value
#define START_OF_VIDEO_MEMORY 0xA000

main() {
char *v = START_OF_VIDEO_MEMORY;
*(v + 5) = 60;
}

This would write the value 60 at five bytes after the start address of video memory. With code like this a developer could write directly to the video card; do tricks, make fast games....etc.

In modern operating systems this is impossible due to virtual memory. In a system like 32-bit Windows each program sees memory as 4GB all of it available to itself. The operating system does a lot of work to keep programs from taking each others' memory and keep each program thinking it owns all memory on the machine. This means that the address 0xA000 no longer means anything special; it's just a part of the virtual address space that could be valid or invalid for the running process (if it's valid, writing to it will change some unknown part of your program; if invalid your program will crash).

This leads to things like DirectX...etc to make game programming faster on Windows; but does that mean pointers for direct access are no longer useful?

Well, sometimes they're still useful. For example some hardware devices (sensors, robot controllers...) will take the virtual memory system to their advantage; the device's driver will map some memory on the device itself to memory in your program! This means you can use pointers to read or write directly to the device memory. It usually goes like this:

#include "sensor.h"
main() {
char * p = sensor_map_memory( "mySensorDeviceName");
// do what you want with p...
sensor_unmap_memory(p);
}

We've taken a nice journey now, and saw why C has a reputation for being suitable for low-level code; took a look into abstraction and dynamic memory, and hopefully understood pointers at a deeper level. I hope you liked the article!