مقالين

احاول حاليا كتابة مقال و اعادة صياغة مقال سابق.

المقال الاول عن سطح المكتب في لينكس و كيف يمكن تحسينه و هو باللغة الانكليزية.

المقال الثاني (باللغة العربية) هو مجموعة افكار عن المصادر المفتوحة و الملكية الفكرية و النهوض بالصناعة التقنية (البرمجية خصوصا) في العالم العربي. هو مقال تقريبا قديم لكني اعيد كتباته من جديد .. لتوضيح بعض الافكار و التقليل من النبرة الحادة فيه، و تحويله من “عراك” نوعا ما، الى نقاش هاديء بعض الشيء.

في هذه المرحلة اعتبر ان كلا المقالين غير منتهيان و هما قيد المراجعة، اي تعليق او ملاحظات للتحسين مرحب بها.

البداية من الصفر ام استخدام مكتبة جاهزة؟

مشروعي اللذي افكر فيه حاليا هو محرر نصوص داخل المتصفح يدعم العربية بشكل محترم، و الفكرة خطرت ببالي حين شاهدت مشروع bespin و اللذي هو عبارة عن محرر اكواد يعمل على الويب، و الفيكة في المشروع (الطريف فيه) ان المحرر معمول عن طريق canvas، مما يعني التخلص من مشاكل محررات النصوص التقليدية على الانترنت المعمولة باساليب عقيمة مثل contentEditable او عن طريق سلسلة كبيرة من الـ divs

و لكن المشكلة في استخدام الـ canvas انك يجب ان تطور جميع خصائص محرر النصوص من الصفر!! ما عدا حتة رسم النص بحد ذاته .. هذه يعملها الـ canvas عن طريق fillText و اخواتها

لكن مشكلة bespin انه ليس مجرد محرر اكواد، بل هو اقرب ربما الى محاولة IDE يعني المحرر جزء صغير من المشروع.

الحقيقة تفاجئت حين نزلت الكود و بحثت عن كود المحرر .. لاكتشف ان محرر النصوص مجرد plugin و ليس هو الجزء الرئيسي من المشروع!!

و الحقيقة انني اريد فقط صنع محرر النصوص دون ان ادوخ نفسي بتفاصيل اخرى لمشروع bespin، و لدي شعور ان العملية لن تكون سهلة لو بدأت من bespin،

و بما انني مبرمج كسول، و لا احب الخوض في تفاصيل bespin … اظن انه سيكون من الاسهل علي ان ابدأ من الصفر .. اي احاول فهم كيفية عمل الـ canvas و محاولة صنع محرر بدائي جدا عن طريقه .. و من ثم تطويره عن طريق سرقة اجزاء من bespin حسب الحاجة!!

اللذي ساكسبه هو الوقت، فتعلم اساسيات الـ canvas و البدء بالتطوير عليه مباشرة و من ثم استعارة اجزاء من bespin لملء الفراغات يمكن ان يتم بشكل اسرع من محاولة فهم و تفكيك هيكل مشروع اخر يعتمد على plugins

كما ان تعلم الـ canvas سيكون اكثر متعة بالتأكيد .. و معه متعة تطوير محرر نصوص على الويب من الصفر (تقريبا)،

بل ربما يمكن دعم العربية بشكل افضل لو تم تصميم المحرر من الصفر، لانه سيمكن حينئذ تصميم هيكله من البداية ليدعم العربية بشكل محترم

ابقوا معنا ..

بالمناسبة، رمضان مبارك للجميع :)

hmm, common lisp? maybe not

Maybe arc?

The thing that’s really attracting me to lisp is the fuss about “macros”.

At first sight, it seems that macros in lisp are necessary because the lisp syntax is very poor and limited.

But, what if this is actually a good thing?

One thing I’m concerned about is, what if my day to day python activity consists of (what would in lisp be) manual expansion of macros? (so called patterns).

I’m not aware of many “patterns” in python, but there are things that I wish can be written more succinctly.

Like, instead of saying:

dict(a=a,b=b,c=c)

why can’t I just say:

m_dict(a,b,c)?

The only time in python where ‘symbols’ are treated as ‘strings’ is keyword arguments.

in dict(a=a), the first a ends up being a string ‘a’, and the second a ends up being the actual a.

Django uses this trick to make querying easy, e.g. query.filter(field__is='value')

From the arc tutorial:

One of the things you’ll discover as you learn more about macros is how much day-to-day coding in other languages consists of manually generating macroexpansions. Conversely, one of the most important elements of learning to think like a Lisp programmer is to cultivate a dissatisfaction with repetitive code. When there are patterns in source code, the response should not be to enshrine them in a list of “best practices,” or to find an IDE that can generate them. Patterns in your code mean you’re doing something wrong. You should write the macro that will generate them and call that instead.

What does linux feel like?

From Big Think Interview With David Heinemeier Hansson:

I felt exactly the same way. I was absolutely not convinced that I was going to be a programmer when I was working with PHP and Java.

He’s talking about the experience of moving from Java to Ruby.

I can say the same thing about linux ^_^

There were times when I was doing work under windows where I just got burned a lot and I was feeling that maybe programming is not for me after all. I was using python, but it was still windows, and while the language itself was awesome, the windows environment sucked horribly.

نواقص في دعم العربية - في جميع الانظمة الحديثة

تخيل انك تريد ان تكتب:

#linuxac

كيف ستظهر لو كتبت في وسط سطر عربي؟؟ هكذا: #linuxac
هل تلاحظون اين المشكلة؟ علامة # على اليمين بدلا من اليسار!! قد تظن انه يمكن وضعها داخل كود، أي #linuxac و لكن هذا لا يفي بالغرض! فسيظل الاتجاه العام للنص هو RTL حتى داخل code span، فمالحل اذن؟

الحل “الرسمي” هو بوضع رمز يونيكود خفي قبل علامة # يشير الى ان اتجاه الكلمة هو LTR، هكذا: ‎#linuxac و هذه العلامة اسمها LRM، اي: Left-to-Right mark

نفس الشي لو اردت كتابة C++، ستظهر الـ + على اليسار، اي بعد السي، و لكن نحن نريدها ان تكون جزءا من الكلمة الانكليزية، لهذا نضع LRM بعد اخر +، اي هكذا: C++‎، و هكذا يصبح اتجاه الكلمة صحيحا.

يفترض ان هذه الامور تدار من قبل محرر النصوص: يعني لو كنت تعمل في محرر نصوص يدعم العربية بشكل محترم، يفترض ان يعرف تلقائيا انك الان تكتب بالانكليزي و يضع الرموز المناسبة من تلقاء نفسه.

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

السؤال هو، هل يمكن ان نستوحي قواعد بسيطة تجعل المحرر يعرف اين يضع الرموز المناسبة، مع حذفها تلقائيا حين تنتفي الحاجة لها؟ كل هذا مع اعطاء المستخدم تحكما كاملا بكيفية وضع هذه الرموز من دون ان يقف المحرر في الطريق؟

اتذكر ايام الوندوز ان Word كان يقوم بكتابة C++ بشكل صحيح، كيف؟ اظن الان ان ما كان يفعله هو ما كنت اقوله قبل قليل: بوضع رمز LRM بعد نهاية الكلمة، اي هكذا: C++‎

بعض الحركات البهلوانية في بايثون functional stuff in python

هذا الموضوع ماخوذ عن حوار في ‎#linuxac

ما هو الـ self في بايثون؟؟

تخيل ان عندك كائن obj من كلاس kls

حين تنادي:

obj.method()

لا تمرر شيئا الى method، و لكن عندما تعرفه داخل الكلاس، يجب ان تضع self:

def method(self):
    ....

لماذا؟
حسنا، لماذا بالضبط؟ لان مؤلفي بايثون هكذا ارادو،
و لكن يبقى السؤال، لماذا؟ هل هناك فائدة؟

نعم، هناك فائدة.

حين تنادي obj.method، قد تظن انك تنادي نفس الـ method المعرف داخل الكلاس، و لكن الحقيقة ليست كذلك.

الحقيقة انك تاخذ العضو method من الكائن obj و تقوم بمناداته — و انت لا تعرف حقيقة ما هو method، قد يكون function عادي، و قد يكون اكثر من ذلك ;)

كيف يكون اكثر من ذلك؟

في الحقيقة ان obj.method يقوم تلقائيا بتمرير الكائن obj الى الـ method المعرف داخل الكلاس.

كيف يمرره تلقائيا؟

حسنا، لغة بايثون تحتوي على خصائص الـ functional programming، اي يمكن تمرير فنكشن الى فنكشن اخر كبارامتر، و يمكن ارجاع فنكشن من فنكشن اخر، و يمكن تعيين فنكشن الى متغير و من ثم استدعاء الفنكشن عن طريق المتغير.

تخيل معي هذا الفنكشن البسيط جدا:

def f(x): print x

مجرد ياخذ كائن (رقم او نص .. او اي شيء) و يطبعه على الشاشة.

و الان تخيل:

def g(): f(10)

مجرد “بروكسي” بين الرقم 10 و بين الفنكشن f، يقوم بطباعة الرقم 10 عن طريق تمريره الى f

طيب، كل شي سهل لحد الان و يمكن فعل هذه الحركة حتى في سي و جافا.

و الان .. اول حركة بهلوانية:

def magic():
    x = 10
    def ninja():
        print x
    ninja()
    x = 20
    ninja()

ماللذي يحصل هنا؟؟ عرفنا فنكشن نينجا داخل ماجك، يقوم نينجا بطباعة الكائن x، و لكن الكائن x معرف خارج ننجا، و مع ذلك يمكنه الوصول اليه.

و الان لو عرفنا اكس على انه 10 قبل تعريف نينجا و قمنا باستدعائه، اكيد سيقوم بطباعة 10. و لكن لو غيرنا اكس الى 20، و قمنا باستدعاء نينجا، فإنه سيقوم بطباعة 20، اي ان الاكس داخل نينجا هو نفس الاكس اللذي نقوم بالتلاعب به.

def magic():
    x = 10
    def ninja():
        print x
    return ninja

هنا نقوم بتعريف نينجا داخل ماجك و نقوم بارجاعه الى من يستدعي ماجك

>>> magic()
<function ninja at 0x872b72c>

يعني عندما استدعينا ماجك، حصلنا على فنكشن اسمه ninja، يمكننا تخزين هذا الفنكشن في متغير و استدعائه:

>>> a = magic()
>>> a()
10

و هنا سنحصل على الرقم 10 .. و هو القيمة المخزنة داخل اكس .. المعرف داخل ماجك!

هل لاحظتم ماللذي حصل هنا؟ اكس معرف داخل ماجك، و لكنه لم يمت بمجرد الخروج من ماجك كما كان سيحدث لو كنا نبرمج في سي او جافا.

هذه الحركة اسمها closure، و يمكن البحث في كووكل عن closure functional programming للمزيد من الشروح

في السابق رأينا ان g هو مثل البروكسي بين 10 و بين f، و لكن في ماجك فإن ماجك نفسه ليس بروكسي، و لكنه يقوم بإنشاء بروكسي (نينجا) و ارجاعه لنا.

و الان ناتي الى المرحلة التالية، حيث نقوم بانشاء بروكسي لاي كائن اخر بطريقة ديناميكية:

def bind(obj):
    def kungfu():
        return f(obj)
    return kungfu

هنا وظيفة بايند ان يقوم بربط كائن ما مع الفنكشن f عن طريق انشاء بروكسي اسمع كون فو

>>> bind(5)
<function kungfu at 0x872b7d4>

هنا قام بايند بربط الرقم 5 مع f و اعطانا فنكشن (بروكسي) يقوم بتمرير 5 الى f

يمكن استخدامه بهذا الشكل:

>>> a = bind(5)
>>> b = bind(10)

هنا، a عبارة عن فنكشن يطبع 5، و b عبارة عن فنكشن يطبع 10

>>> a()
5
>>> b()
10

هل فهمتم شيئا؟

الموضوع صعب اذا كانت هذه اول مرة ترى مثل هذه الاشياء، و يحتاج فترة للهضم.

و الان، يمكننا انشاء بروكسي بين اي كائن و بين f:

>>> my_object = 10
>>> g = bind(my_object)
>>> g()
10

لاحظ هنا ان g يحتوي في داخله على كود يقوم بتمرير my_object تلقائيا الى f

يعني تخيل ان my_object هو ليس مجرد رقم 10 بل هو كائن مركب .. و نستطيع بكل بساطة ان نقوم بالصاق فنكشن جديد الى هذا الكائن بهذا الشكل:

my_object.f = bind(my_object)

هنا، نستطيع ان نستدعي:

my_object.f()

و هذا الـ f سيقوم بتمرير my_object تلقائيا الى الفنكشن الاصلي f اللذي عرفناه في البداية على انه يقوم بطباعة الكائن على الشاشة.

و لكن لنعد الى الفنكشن bind، شمعنى يعني فقط يمرر الى f؟

يمكننا تطويره قليلا و جعله يربط بين اي فنكشن و اي كائن مهما كان:

def bind2(object, function): 
    def inner():
        return function(object)
    return inner

لاحظ ما يحدث هنا:

my_object.f = bind2(my_object, f)

هنا تقريبا نفس ما يحصل في بايثون نفسها (بشكل مبسط جدا جدا) حيث نقوم باضافة حقل f الى الكائن my_object و هذا الحقل هو في الحقيقة فنكشن يقوم بتمرير الكائن الى الفنكشن f الرئيسي

الفرق ان بايثون تقوم بربط الكائن بالفنكشن عن طريق types.MethodType و هو يقوم بشيء مماثل تقريبا، و لكنه ليس فنكشن بل كلاس (constructor)، و ياخذ بارامتر اضافي و هو الكلاس، و طبعا لانه كلاس، فلا يقوم بارجاع فنكشن حقيقي بل يقوم بارجاع كائن يمكن استدعائه لانه يطبق خاصية __call__

يمكننا تخيل ما يحدث على هذا الشكل:

تخيل كلاس اسمه M و ليكن فارغا:

class M(object): pass
a = M()

ننشيء منه كائن و نسميه a

و الان نعرف فنكشن جديد:

def method1(self):
    print self.x

و الان نقوم بربط هذا الفنكشن مع الكائن a

a.m = types.MethodType(method1, a, M)

و هنا نلاحظ ان الحقل m هو عبارة عن “ميثود” بكل ما تعنيه الكلمة من معنى (في بايثون على الاقل)، و نلاحظ ان الفنكشن method1 ياخذ بارامتر هو self، و لكننا حين نستدعي a.m لا نمرر شيئا الى الفنكشن، و هذا لان الكائن a نفسه يمرر تلقائيا.

What do hackers want? Like all craftsmen, hackers like good tools. In fact, that’s an understatement. Good hackers find it unbearable to use bad tools. They’ll simply refuse to work on projects with the wrong infrastructure.