جدول المحتويات
لماذا بايثون ؟
حول هذه الوثيقة
هذا مقال مترجم يتحدث عن أهمية لغة بايثون (ولا يشرح طريقة البدء بتعلمها) وما تمتاز بها مقابل لغات أخرى من وجهة نظر شخص يجيد عدد كبير من لغات بل كتب بنفسه عددا منها.
- تأليف: إريك ريموند Eric Raymond المعروف اختصاراً ESR وهو مؤيد ناشط لنظام لينكس ومؤلف The Cathedral & The Bazaar يمكن مراسلته على esr@thyrsus.com
- المقال الأصلي نشرته عدة مواقع منها
مقدمة
نظرتي الأولى للغة بايثون كانت مصادفة، ولم أحب ما رأيته في ذاك الوقت كثيراً. وكان ذلك في بداية 1997، وقتها كان كتاب برمجة بايثون Programming Python لمؤلفه مارك لوتز Mark Lutz من أورالي قد صدر تواً. وكتب اورالي تأتي عتبتي من حين لآخر ينتقيها لي من بين إصداراتهم متبرع غامض داخل المؤسسة من خلال عملية عشوائية يأست من فهمها.
أحدها (كتاب من أورالي) كانت برمجة بايثون Programming Python. وقد وجدت هذا ممتعاً بطريقة ما، حيث أني أجمع لغات الحاسوب. فأنا أعرف أكثر من دزينتين من اللغات عامة الأغراض، وأكتب عدداً من المصنفات compilers والمفسرات interpreters للمتعة، وقد صممت أي عدد من اللغات خاصة الأهداف وأشكال الإرقام markup formalisms بنفسي. آخر مشاريعي المكتملة أثناء كتابة هذه المقالة، لغة خاصة الأهداف اسمها SNG للتعامل مع ملفات صور PNG. إذا كنت مهتماً انظر للصفحة الرئيسية www.catb.org/~esr/sng كذلك كتبت بعض لغات البرمجة عامة الأغراض الشاذة في معرض الحوسبة الرجعية www.catb.org/retro
لقد سمعت بالفعل عن بايثون بما يكفي أن أعرف أنها -كما يسمى في وقتنا الحاضر- لغة نصية “سكربتية” scripting language ، ولغة تفسيرية تتمتع بإدارة جيدة للذاكرة مدمجة بها،وحسن إدارة الموارد للاستدعاء والتعاون مع البرامج الأخرى. لذا فإنني غصت في برمجه بايثون ،وسؤال واحد يدور فى خاطري : ما الذي لدى هذه اللغة وليس لدى بيرل مثله ؟!
بيرل بالطبع ؛ هي عملاق برمجة السكربت الحديثة ، وقد حلت إلى حد كبير- محل لغة برمجة شل سكربت ، كخيار لمديري النظام . وذلك -جزئيا- بفضل مكتبة يونيكس الشاملة ونداءات النظام ، وكذلك بفضل المجموعة الهائلة من وحدات بيرل البرمجية والتي بنيت من قبل مجتمع بيرل البالغ النشاط . وعموما تشير التقديرات إلى كونها لغة الواجهة المشتركة لبوابة الشبكة-CGI -common gateway interface و التي تقف وراء حوالي 80% من المحتوى الحي على الشبكة .
“لاري وول” مؤلف لغة بيرل يعتبر بحق واحدا من أهم قادة مجتمع المصادر المفتوحة ،وغالبا ما يأتي في المرتبة الثالثة بعد لينوس تورفالدز وريتشارد ستولمان ضمن عظماء الهاكرز “المقدسين” في الوقت الحاضر .
في ذلك الوقت ، كنت أستخدم بيرل لعدد من المشروعات الصغيرة. وقد وجدت أنها قوية جدا ، حتى لو كانت الصياغة وبعض الجوانب الأخرى من اللغة تبدو قاصرة وواهية وقد تنقض عليك إذا لم تستخدم بعناية. وبدا لي أن بايثون مثل جبل آخر علي صعوده بشق الأنفس كأي لغة برمجة نصية أخرى، وكلما قرأت أكثر عنها كنت أبحث عما يمكن أن يميزها عن بيرل.
وعلى الفور تعثرت بأول سمة من سمات بايثون الغريبة والتي يمكن للجميع ملاحظتها : وهي أن المسافات الفارغة (أو “الإزاحة البادئة” indentation) لها أهمية كبيرة في صيغة اللغة. واللغة لا تشبه سي أو بيرل في استخدام الحاصرة في التراكيب، وبدلا من ذلك تفصل مجموعة العبارات عبر التغيّر في الإزاحة. ومثلما وقع لمعظم الهاكرز عند إدراكهم الأول لهذه الحقيقة، ولّيت منها مشمئزا.
وأنا كبير بما يكفي أن أكون قد أمضيت شهورا من سبعينات القرن العشرين على فورتران. بعكس معظم الهاكرز هذه الأيام (الذين لم يتعاملوا مع فورتران). ومع ذلك يبدو أن ثقافتنا تميل -إلى حد ما- إلى الإبقاء على ذكرى دقيقة عن هذا الطراز القديم والكريه ذي الحقول الثابتة في لغات البرمجة1). والواقع أن مصطلح “الهيئة الحرة free format” (نقيض اللغة التي تضع قيود وتكون المسافات فيها ذات دلالة) المستخدم في ذلك الوقت لوصف أحدث تركيب لغوي مبني على القطع tokens كما في باسكال و سي،أصبح -تقريبا-في طي النسيان ،وقد تم تصميم جميع اللغات -أو أغلبها- بهذا الأسلوب لعدة عقود الآن.على أية حال؛ من الصعب إلقاء اللوم على أي شخص على رؤية هذه الميزة في بايثون كأنه داس على كومة رطبة من روث الديناصور التي لا زال البخار يتصاعد منها.
وهذا بالتأكيد ما شعرت به. تصفحت شرح هذه اللغة على عجل دونما اهتمام كبير. ولم أر ما يمكن أن يزكي بايثون، عدا ما يبدو من كونها أنظف في الصياغة اللغوية من بيرل ، والتسهيلات التي تقدمها للعناصر الأساسية في الواجهة الرسومية للمستخدم مثل الأزرار والقوائم، والتي -بأمانة-تبدو جميلة.
أعدت الكتب إلى الرّف ملصقاً ملاحظة على عقلي بأن علي أن أكتب بعض الكود لبرنامج ذو واجهة رسومية GUI بلغة بايثون في وقت ما، لا لشيء إلا لأثبت أني فهمت اللغة. لكني لم أكن مقتنعا أن ما رأيته منها يمكن أن ينافس بيرل.
تكشف بيرل
ولقد تآمرت كثير من الأمور الأخرى لإبقاء تلك الفكرة في ذيل قائمة أولوياتي لعدة أشهر. وقد كان ما تبقى من عام 1997 حافلا بالأحداث بالنسبة لي ، ومن ضمن الأمور الأخرى أنه العام الذي كتبت ونشرت فيه النص الأصلي لكتاب “الكاتدرائية والسوق”. وقد وجدت وقتا لكتابة عدة برامج بيرل ، ومن ضمنها برنامجان كبيرا الحجم ومعقدان . أحدهما :Keeper، وهو برنامج مساعد ما يزال يستخدم في السيطرة على الطلبات القادمة لأرشيف برنامج metalab . وهو يقوم بتوليد صفحات الويب التي تراها في metalab.unc.edu/pub/Linux/!INDEX.html. والبرنامج الآخر ، anthologize ،ويستخدم لتوليد PostScript تلقائيا في الإصدار السادس الخاص بلينكس من مشروع أرشيف وثائق لينكس من howtos. وكلا البرنامجين متوفر على metalab
كتابة هذه البرامج ترك فيّ تدريجياً عدم رضى عن بيرل. كلما كبر حجم المشروع فإن المنغصات في بيرل تتضخم إلى مشاكل جدية ومستمرة. الصياغة التي بدت سلسة عند مئة سطر بدأت تصبح سياجاً منيعاً من الأشواك عند الألف. “هناك أكثر من طريقة للقيام بها”2) أعارنا النكهة والتعبير بالقليل. لكنه صعب المحافظة على نسق واحد على قاعدة كبيرة من الكود. والعديد من المزايا التي تم رقعها فيما بعد في بيرل لمواجهة التحكمات المعقدة التي تتطلبها البرامج الكبيرة (الكائنات، تحديد النطاق scoping وجملة use strict
لزيادة الصرامة …)
الذي يعطيني شعور بأنه هش ومتكلف وبني دون أساس.
هذه المشاكل مجتمعة تعطي أكواما كبيرة من كود بيرل صعب القراءة أو الفهم ككل دون مبرر حتى لو غبت عنه أيام قليلة من تاريخ كتابته. كذلك وجدت أني أضيع الكثير من الوقت مصارعا اللغة أكثر مما أنفق من وقتي على التركيز في حل مشاكل التطبيق البرمجي. وأسوأ من كل هذا أنك تحصل على كود بشع “لعين”. هذا مهم لأن البرامج البشعة (يقصد كودها) مثل الجسور المعلقة البشعة فهي أكثر عرضة للانهيار وذلك يعود لطريقة إدراك الإنسان (خاصة إن كان مهندسا) لمفهوم الجمال وهو مرتبط بقدرتنا على معالجة وفهم التعقيد. اللغة التي تصعّب عليك كتابة كود أنيق تصعّب عليك كتابة كود جيد.
وحيث أن جعبتي تحوي أكثر من دزينتين من اللغات وحيث أني قادر على اكتشاف كل ما ترويه علامات تصميم اللغة إن دفعت إلى أقصى حافة ما تنطوي عليه من وظائف. في منتصف العام الميلادي 1997 كنت أفكر “لا بد أن هناك طريقة أفضل” وشرعت أبحث عن لغة نصية بديعة (أبلغ أو أجمل).
ما لم يكن بحسباني هو العودة إلى سي كي تكون لغتي التلقائية. لقد ولت الأيام التي كنت فيها تدير الذاكرة في برامجك بنفسك إلا مجالات متخصصة بعينها مثل النواة والحوسبة العلمية والرسم ثلاثي الأبعاد، تلكم الأماكن التي ينبغي عليك فيها الحصول على أقصى سرعة وأن تتحكم بدقائق استخدام الذاكرة حيث عليك أن تدفع بالعتاد بأقصى ما يمكن.
في أغلب الحالات على أجهزة اليوم فإنه من الجنون أن نقبل عبء التمحيص في زلاّت تجاوز حدود ذاكرة buffer ومشاكل pointer-aliasing وتسرب الذاكرة بين دالتي malloc/free وغيرها من “الأمراض”. بل إن الصفقة الرابحة هي أن نتحمل فقدان دورات قليلة من وقت المعالج وكيلوات محدودة من الذاكرة الناتجة عن إدارة اللغات النصية scripting language للذاكرة ومقابل هذا نوفر الكثير من وقت البشر الثمين. وفي الحقيقة إن فوائد تلك الاستراتيجية هي السبب في الانفجار الكبير في نمو استخدام لغة بيرل منذ أوساط تسعينات القرن العشرين.
وبمجرد أن داعبت لغة Tcl اكتشفت بسرعة أنها لا تناسب المشاريع الكبيرة بطريقة أسوأ من بيرل. ولأني مبرمج LISP قديم فقد ألقيت نظرة على العديد من “لهجات” LISP و Scheme وحدث ما يشهد التاريخ بأنه طبيعي في عالم LISP وهو الكثير من التصميم الذكي يضيع بسبب الوثائق الهزيلة هذا إن وجدت الوثائق أضف إلى ذلك عدم اكتمال الوصول إلى مرافق POSIX/UNIX وتشعب مجتمع المستخدمين بشكل عميق ومتأصل. فشعبية بيرل لم تحدث صدفة. حيث أن كل منافسيها أسوأ منها في المشاريع الكبيرة أو أنها لا تكون مفيدة مثلها بالقدر الذي كان يفترض أن يجعل تصميمها الأفضل.
إعادة النظر في بايثون
نظرتي الثانية لبايثون كانت تقريبا صدفة كالصدفة الأولى. في تشرين الأول من عام 1997, حيث أظهرت سلسلة من الأسئلة على قائمة أصدقاء fetchmail البريدية 3) أن المستخدمين النهائيين يعانون مشاكل متزايدة في توليد ملفات الإعدادات لبرنامج fetchmail الخاص بي. صيغة هذا الملف حرة الهيئة free-format مألوفة في يونكس، لكنها يمكن أن تكون معقدة عندما يملك المستخدم حسابات مثل POP3 و IMAP على مواقع متعددة. وكمثال انظر اللائحة الأولى LISTING1 حيث تشاهد نسخة مبسطة من إعداداته عندي
LISTING 1: fetchmail Configuration File
set postmaster "esr" set daemon 300 poll imap.ccil.org with proto IMAP and options no dns aka snark.thyrsus.com locke.ccil.org ccil.org user esr there is esr here options fetchall dropstatus warnings 3600 poll imap.netaxs.com with proto IMAP user "esr" there is esr here options dropstatus warnings 3600 skip imap.21cn.com with proto IMAP user esr here is tranxww there options fetchall skip pop.tems.com with proto POP3: user esr here is ed there options fetchall skip mail.frequentis.com with proto IMAP: user esr here is imaptest there with options fetchall
قررت أن أهاجم المشكلة بكتابة محرر إعدادات صديق للمستخدم اسمه fetchmailconf. وكان هدف التصميم واضحا: أن يخفي تماما تعقيدات صيغة ملف التحكم (الإعدادات) خلف واجهة رسومية أنيقة مزودة بأزرار التحديد والشرائط المنزلقة والنماذج التي يمكن ملؤها.
وفكرة تضمين هذا كله في بيرل لم أتحمس لها مطلقا. فقد رأيت كود الواجهة الرسومية في بيرل، وكان خليطا متنافرا بين بيرل وTcl. وبدا أبشع بكثير من كود بيرل الخالص الذي كتبته. وعند هذه النقطة تذكرت الجزء الذي كنت وضعته منذ أكثر من ستة شهور قبل ذلك. قد تكون هذه فرصة سانحة للحصول على بعض الخبرة العملية في بايثون.
وقطعا هذا أعادني وجها لوجه مرة أخرى إلى كون المسافة البادئة مهمة في بايثون. لكن هذه المرة استبقت ذلك بالتهام بعض الكود لبعض الأمثلة لعناصر من الواجهة الرسومية. الغريب أن استخدام بايثون للمسافات لم يعد غير طبيعي في أقل من 20 دقيقة. كل ما علي هو أن أنسق الكود كما كنت أفعل أنا بطبعي في سي بأي حال (مع أن سي لا تشترط ذلك) وكان الكود يعمل.
كانت تلك أول مفاجئة لي. الثانية جاءت بعد بضع ساعات في المشروع عندما لاحظت (وهذا سمح بوقفات لازمة كي أطّلع على مزايا جديدة في بايثون) أني كنت أكتب كودا يعمل تقريبا بالقدر الذي تسعفني فيه سرعتي في الطباعة. عندما أدركت هذا ذهلت. إن من أهم مقاييس الجهد اللازم لكتابة كود برنامج هو المقدار الذي تتكرر فيه حالة أن تكتب شيء ثم تدرك أنه لا يتطابق مع تصورك للمسألة وتحتاج أن تتراجع مدركا أن ما كتبته لم يخبر اللغة ما كنت تفكر فيه. وأما مقياس التصميم الجيد للغة هو أنه كلما وقع هفوات مثل هذه تكسب خبرة أكثر في اللغة.
فعندما تكتب كود بالقدر ذاته من سرعة طباعتك وعندما تكون الهفوات قريبة من الصفر فإن هذا يعني أنك أصبحت أستاذا في تلك اللغة. لكن هذا غير منطقي فهذا يومي الأول معها وأنا لا زلت أتوقف لأنظر في هذه اللغة الجديدة ومكتبتها!
كان هذا أول علامة دلتني على أني أمام تصميم استثنائي جيد في بايثون. أغلب اللغات بها طاقة احتكاك تعرقل سرعتك وغرابة مزروعة في تصميمها تحتاج أن تتعلمها قبل أن ينخفض معدل هفواتك لرقم قريب من الصفر. بايثون كان أول لغة برمجة عامة الأغراض شاهدتها قط عكست تلك العملية.
فأنا لم أستغرق وقتا في تعلم مزاياها. وها أنا ذا أكتب برنامج fetchmailconf عامل وفعّال بواجهة رسومية في 6 أيام عمل منها ما يقدر يومي عمل أمضيتهما في تعلم بايثون.
وهذا يعكس ميزة أخرى مفيدة لهذه اللغة: أنها مختزلة compact يمكنك أن تحتفظ في ذهنك بكل طاقم مزاياها (أو على الأقل بفهرس المفاهيم في مكتبتها). هذه أيضا من مزايا سي أما بيرل فقطعا لا لأن ذلك هو ثمن شعارها “هناك أكثر من طريقة للقيام بها!”.
حفراً إلى الأعماق
أكبر لحظات الاكتشاف دراماتيكية تقع أمامنا. كان في تصميمي مشكلة: حيث من السهل أن أولد ملفات الإعدادات من الواجهة الرسومية GUI لكن تحريرها كان مسألة أصعب. بل تحديدا قراءة تلك الملفات إلى هيئة يمكن تحريرها تلك هي المشكلة. برنامج الإعراب parser لهيئة ملفات إعدادات fetchmail دقيق جدا. كتب تحديدا على YACC و Lex أداتي يونكس الكلاسيكيتين لتوليد كود سي لإعراب اللغات. من أجل أن يتمكن fetchmailconf من تحرير الإعدادات الحالية كنت أظن أنه علي أن أكرر كود الإعراب الدقيق في لغة بايثون. لكني كنت أكره هذه الفكرة لأنها تتطلب الكثير من العمل ولأني لم أكن واثقا أن برنامجي إعراب منفصلتين في لغتين منفصلتين سينسجمان. آخر شيء قد أرغب به هو أن أضيف على نفسي تعب مواكبة البرنامجين لبعضهما البعض أثناء تطور لغة الإعدادات!
هذه المشكلة أربكتني لفترة. ثم فُتح علي: سأترك fetchmailconf يستخدم نفس الإعراب الموجود داخل fetchmail! حيث أضفت خيارا اسمه –configdump إلى fetchmail يقوم فيه fetchmail بإعراب ملف الإعدادات .fetchmailrc ثم يقوم بإخراج الناتج للمخرجات القياسية على شكل ثابت استهلال في بايثون. الملف السابق يعطي مخرجات كما في اللائحة رقم 2 (بعض البيانات غير ذات الصلة أهملت لتوفير المساحة)
Listing 2: fetchmailrc
fetchmailrc = { 'poll_interval':300, "logfile":None, "postmaster":"esr", 'bouncemail':TRUE, "properties":None, 'invisible':FALSE, 'syslog':FALSE, # List of server entries begins here 'servers': [ # Entry for site `imap.ccil.org' begins: { "pollname":"imap.ccil.org", 'active':TRUE, "via":None, "protocol":"IMAP", 'port':0, 'timeout':300, 'dns':FALSE, "aka":["snark.thyrsus.com", "locke.ccil.org", "ccil.org"], 'users': [ { "remote":"esr", "password":"Malvern", 'localnames':["esr"], 'fetchall':TRUE, 'keep':FALSE, 'flush':FALSE, "mda":None, 'limit':0, 'warnings':3600, } , ] } , # Entry for site `imap.netaxs.com' begins: { "pollname":"imap.netaxs.com", 'active':TRUE, "via":None, "protocol":"IMAP", 'port':0, 'timeout':300, 'dns':TRUE, "aka":None, 'users': [ { "remote":"esr", "password":"d0wnthere", 'localnames':["esr"], 'fetchall':FALSE, 'keep':FALSE, 'flush':FALSE, "mda":None, 'limit':0, 'warnings':3600, } , ] } , # Entry for site `imap.21cn.com' begins: { "pollname":"imap.21cn.com", 'active':FALSE, "via":None, "protocol":"IMAP", 'port':0, 'timeout':300, 'dns':TRUE, "aka":None, 'users': [ { "remote":"tranxww", "password":None, 'localnames':["esr"], 'fetchall':TRUE, 'keep':FALSE, 'flush':FALSE, "mda":None, 'limit':0, 'warnings':3600, } , ] } , # Entry for site `pop.tems.com' begins: { "pollname":"pop.tems.com", 'active':FALSE, "via":None, "protocol":"POP3", 'port':0, 'timeout':300, 'dns':TRUE, 'uidl':FALSE, "aka":None, 'users': [ { "remote":"ed", "password":None, 'localnames':["esr"], 'fetchall':TRUE, 'keep':FALSE, 'flush':FALSE, "mda":None, 'limit':0, 'warnings':3600, } , ] } , # Entry for site `mail.frequentis.com' begins: { "pollname":"mail.frequentis.com", 'active':FALSE, "via":None, "protocol":"IMAP", 'port':0, 'timeout':300, 'dns':TRUE, "aka":None, 'users': [ { "remote":"imaptest", "password":None, 'localnames':["esr"], 'fetchall':TRUE, 'keep':FALSE, 'flush':FALSE, "mda":None, 'limit':0, 'warnings':3600, } , ] } ] }
عندها كل ما على بايثون أن تحسب evaluate تلك المخرجات وعندها ستكون الإعدادات هي قيمة المتغير fetchmail.
لم تكن هذه آخر خطوة في “الرقصة”. ما كنت أريده لم يكن وصول fetchmailconf إلى الإعدادات الحالية، بل أن يحولها إلى شجرة هرمية مترابطة من كائناتٍ حية. هناك 3 أنواع من الكائنات في هذه الشجرة: الإعدادات (الكائن ذي أعلى مستوى الذي يمثل الإعدادات كلها)، الموقع (يمثل أحد المواقع التي نريد أن نسحب منها) والمستخدم (تمثل بيانات المستخدم المرتبطة بموقع ما). المثال كان عبارة عن 5 كائنات لمواقع يرتبط بكل واحد مستخدم.
لقد صممت وكتبت صنوف classes للكائنات الثلاثة (هذا ما استهلك 4 أيام أمضيت أغلبها أحاذي الودجات widgets). كل منها لها طريقة (أي دالة) تؤدي إلى إظهار لوحة تحرير تسمح بتحرير بيانات ذاك الكائن الفرد. أي أن كل ما بقي علي هو نقل البيانات المينة من استهلال متغير بايثون إلى كائنات حية.
لقد فكرت في كتابة كود يعلم صراحة بُنية الصنوف الثلاثة ويستخدم ما يعلمه عنها حتى يزحف داخل القيمة الاستهلالية وبناءً على ما يجد فيها ينشئ الكائنات. لكني رفضت تلك الفكرة لأنه من الوارد جدا ظهور عناصر جديدة في الصنوف مع مرور الوقت وزيادة المزايا في لغة الإعدادات. إن عملت كود إنشاء الكائنات بالطريقة البدهية ستكون هشة وتتقادم (تصبح أقدم وغير متزامنة) عند تغيير تعريف الصنوف أو بنية القيمة الاستهلالية.
ما كنت أريده كود يحلل استهلال المتغير شكلا ومضمونا، يستعلم عن تعريفات الصنوف أنفسها وعناصرها ويضبط قيمها لتطابق المجموعتين.
هذا النوع من الأشياء اسمه الصنوف الماورائية metaclass hacking وهو من الأسرار الرهيبة التي تقتصر على علية المبرمجين وكأنها السحر الأسود. أغلب لغات البرمجة الكينونية لا تدعمها وتلك التي تدعمها (مثل بيرل) تكون معقدة وهشة وغير متعهدة بالعناية. لقد أدهشتني بايثون بقلة الاحتكاك فيها (يقصد الإعاقة من طرف اللغة لانسياب الأفكار) وها قد آن أوان اختبار حقيقي لها. كم من الجهد علي أن أبذل في مصارعة اللغة حتى أجعلها تقوم بذلك. أعلم من خبرتي السابقة أن القتال سيكون مؤلما حتى لو كنت أنا الفائز، لكن ما أن غصت في الكتاب وقرأت عن تسهيلات الصنوف الماورائية في بايثون حتى كتبت الدالة في اللائحة 3 واستدعاءها في اللائحة 4.
Listing 3: Metaclass Function
def copy_instance(toclass, fromdict): # Initialize a class object of given type from a conformant dictionary. class_sig = toclass.__dict__.keys(); class_sig.sort() dict_keys = fromdict.keys(); dict_keys.sort() common = intersect(class_sig, dict_keys) if 'typemap' in class_sig: class_sig.remove('typemap') if tuple(class_sig) != tuple(dict_keys): print "Conformability error" # print "Class signature: " + `class_sig` # print "Dictionary keys: " + `dict_keys` print "Not matched in class signature: " + `setdiff(class_sig, common)` print "Not matched in dictionary keys: " + `setdiff(dict_keys, common)` sys.exit(1) else: for x in dict_keys: setattr(toclass, x, fromdict[x])
Listing 4: Code that Calls Metaclass Function
# The tricky part--initializing objects from the # configuration global # `Configuration' is the top level of the object # tree we're going to mung Configuration = Controls() copy_instance(Configuration, configuration) Configuration.servers = []; for server in configuration[`servers']: Newsite = Server() copy_instance(Newsite, server) Configuration.servers.append(Newsite) Newsite.users = []; for user in server['users']: Newuser = User() copy_instance(Newuser, user) Newsite.users.append(Newuser)
هذا لا يبدو سيئا لحيل السحر الأسود أليس كذلك ؟ خلال 32 سطرا بما فيها التعليقات. من خلال معرفتي لما قلته عن تركيب الصنف لاحظ إن كود الاستدعاء مقروء. ليس حجم الكود هو الصدمة فحسب بل إنه يستحق عناقا! هذا الكود استغرقت في كتابته حوالي 90 دقيقة وقد عمل من أول تجربة لتنفيذه
الخلاصة
إن قلت أني ذهلت سيكون ذلك استهانة وتقليل من شأن بايثون. من الجدير بالملاحظة أن تطبيق مهارات بسيطة تعمل تماما كما نتوقع من أول مرة. لكن أن تعمل معي metaclass hack في لغة جديدة علي من أول مرة خلال أقل 6 أيام من بدء تعلمي للغة؟ حتى لو افترضنا أني خارق/هاكر موهوب ومتمرس إلا أن هذه شهادة رائعة تدل على وضوح وكياسة التصميم.
لا يوجد طريقة بسيطة كان يمكن أن أستل مثل تلك النتائج في بيرل مع خبرتي الطويلة فيها. كانت هذه النقطة التي أدركت فيها أن علي أن أترك لغة بيرل ورائي.
كانت تلك أكثر اللحظات دراماتيكية مع بايثون. لكن، بعد أن قلنا ذلك وانتهينا، كانت تلك حركة خرقة خاطفة ذكية. إلا أن فائدة أي لغة على المدى الطويل لا تأتي من دعمها للحيل الخارقة الخاطفة الذكية بل من جودة وبروز الأعمال الرتيبة اليومية التي يحتاجها المبرمج. إن أعمال البرمجة الراتبة لا تتألف من كتابة برامج جديدة بل إن أغلبها من قراءة وتعديل برامج موجودة.
هذه هي الضربة الحقيقية لهذه القصة: بعد أسابيع وشهور من كتابة fetchmailconf، لا زلت أستطيع قراءة الكود واستيعاب ما كان الكود يعمل دون أي جهد عقلي جدي. والسبب الحقيقي أني لم أعد أكتب برامج بلغة بيرل (إلا مشاريع متناهية الصغر) مع أني كنت اكتب أطنان من كود بيرل. أنا أهاب أن أجد نفسي في المستقبل مضطرا لتعديل كود keeper أو anthologize (يبدو أنها أسماء برامج كتبها على بيرل) في حين لا تشكل fetchmailconf أي هاجس لي.
لا زال هناك مكان للغة بيرل للمشاريع مفرطة الصغر (دون 100 سطر) التي تتضمن الكثير من مطابقة أنماط النصوص حيث أني سأفضل حل عبر الأنماط القياسية في بيرل Perl-regexp مقابل بايثون. من أمثلة ذلك ما كتبته مؤخرا كجزء من fetchmail مثل timeseries و growthplot. في الحقيقة هذه الأشياء هي التي كانت تقوم بها بيرل منذ انطلاقتها كمزيج بين awk/sed/grep/sh قبل أن يكون فيها دوال ووصول لواجهة نظام التشغيل البرمجية API. لأي شيء أكبر أو أعقد من ذلك فأني سأفضل مزايا بايثون وأظن أنكم كذلك أيضا.