يجب أن تكون البرمجة الوظيفية هي الأولوية رقم 1 في عام 2015

"منظمة التحرير الفلسطينية لن تكون قادرة على إنقاذنا من سحابة الوحوش."



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

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


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

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

في البداية ، كانت أجهزة الكمبيوتر بطيئة للغاية



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




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

لكن أجهزة الكمبيوتر تحسنت كثيرًا.



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

البرمجة الوظيفية 50.5



هذه المقالة ليست بأي حال مقدمة إلى FI. في نهاية هذا القسم ، ستحتاج إلى معرفة ما هو AF وكيفية بدء رحلتك الدراسية.

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

قائمة (غير كاملة) من ميزات FP:

  1. وظائف الدرجة الأولى
  2. وظائف عالية الترتيب
  3. وظائف نقية
  4. الإغلاق
  5. دولة غير قابلة للتغيير


الآن لا داعي للقلق بشأن هذه المصطلحات الغريبة ، فقط فهم ما تعنيه.

وظائف الفئة الأولى تعني أنه يمكنك حفظ الوظائف في المتغيرات. أنا متأكد من أنك فعلت شيئًا مشابهًا ، كما في مثال JavaScript:

var add = function(a, b){
  return a + b
}

لقد قمت للتو بإنشاء دالة مجهولة تحصل على أ و ب وتعيد أ + ب ، وتعين هذه الوظيفة لمتغير الإضافة . تعني

الدالات ذات الترتيب الأعلى أن الدوال يمكنها إرجاع الدالات أو قبولها كمعلمات.

ومرة أخرى في JavaScript:

document.querySelector('#button')
  .addEventListener('click', function(){
    alert('yay, i got clicked')
  })

أو

var add = function(a){
  return function(b){
    return a + b
  }
}
 
var add2 = add(2)
add2(3) // => 5


يعد كلا الخيارين مثالاً لوظائف الترتيب الأعلى ، حتى إذا لم تكتب شيئًا كهذا ، فقد تكون قد رأيت شيئًا مشابهًا في مكان آخر.

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

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

var add = function(a){
  return function(b){
    return a + b
  }
}
 
var add2 = add(2)
add2(3) // => 5

انظر مرة أخرى إلى المثال الثاني من الفقرة دالات ترتيب أعلى ، تم إغلاق المتغير a وهو متاح فقط في الدالة التي تم إرجاعها. في الواقع ، عمليات الإغلاق ليست سمة من سمات نموذج FP ، بل هي تحسين. تعني

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

let x = 5;;
x = 6;;

print_int x;;  (* prints 5 *)


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

البرمجة الكائنية لا يمكن أن تحميك أكثر



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

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

"ولكن لماذا لا يمكنني الاستمرار في استخدام OOP؟"



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

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

ومن الجدير بالذكر أنه لا يجب التوقف عن استخدام الدولة المتغيرة. يجب علينا استخدام الإدخال / الإخراج (IO) ، إلخ ، حتى تكون برامجنا مفيدة. الفكرة الرئيسية لـ FP هي: استخدم حالة قابلة للتغيير فقط عندما تكون هناك حاجة إليها حقًا.

"أنا لا أعمل مع السحب ، هل أحتاج حقًا لدراسة AF؟"



نعم.

ستساعدك البرمجة الوظيفية على كتابة البرامج بشكل أفضل والتحدث عن المشاكل التي عليك حلها.

"لقد حاولت. إنه أمر معقد للغاية ويصعب قراءة الرمز ".



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

لبدء تعلم FP هو تقريبًا نفس البدء في كتابة البرامج من الصفر مرة أخرى (بغض النظر عن اللغة التي بدأت تتعلمها ، سيكون الأمر بالتأكيد مثل البدء من البداية).

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

تحقق من البرنامج المكتوب بلغة هاسكل وجافا سكريبت (النمط الحتمي):

guess :: Int -> [Char]
guess 7 = "Much 7 very wow."
guess x = "Ooops, try again."

-- strongly inspired by http://learnyouahaskell.com

function guess(x){
  if(x == 7){
    return "Much 7 very wow."
  }
  else {
    return "Oops, try again."
  }
}

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

ما يفعله هاسكل:

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

وهذا هو نفس الشيء الذي تفعله شفرة جافا سكريبت ، لكن هاسكل يعيّن "النمط" الذي أعلنه المبرمج في الشفرة.

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

plus1 :: [Int] -> [Int]
plus1 []      = []
plus1 (x:xs)  = x + 1 : plus1 xs 

-- plus1 [0,1,2,3]
-- > [1,2,3,4]

في البرنامج أعلاه ، * plus1 * هي وظيفة تأخذ قائمة أعداد صحيحة وتضيف 1 إلى كل عنصر من عناصر القائمة. تقارن الوظيفة عندما تكون القائمة فارغة [] (ترجع قائمة فارغة أخرى ، حيث لا توجد عناصر فيها) تتجاوز القائمة غير الفارغة وتحدد نمط المطابقة: x كعنصر أول في القائمة ، xs على أنها القائمة المتبقية. ثم يقوم ببساطة بحساب المجموع ودمجه من خلال مكالمة متكررة.

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

لذلك دعونا نبدأ



تم نشر الكثير من المواد حول البرمجة الوظيفية ، ولكن لا يجب عليك تخطي هذه الروابط بشكل لا لبس فيه:

  1. مبادئ البرمجة الوظيفية في Scala : ستكون الدورة مفيدة لأولئك الذين يعرفون Java ويرغبون في تجربة البرمجة الوظيفية دون القفز من JVM. يغطي المقرر المفاهيم الأساسية.
  2. نماذج برمجة الكمبيوتر - الأساسيات : ستكون هذه الدورة مفيدة لأولئك الذين يرغبون في تعلم كيفية كتابة البرامج بلغة وظيفية. تستخدم الدورة لغة التعلم Qz. هناك الكثير من التمارين في الدورة ، يمكنك استخدام لغة وظيفية ومحاولة إنشاء هيكل البيانات الخاص بك. أعتقد أن الدورة توفر لبنات أساسية لـ "المبنى" المسمى "البرمجة الوظيفية" ، وسوف تساعدك في لغات أخرى في المستقبل.


لسوء الحظ ، ستكون الدورات متاحة فقط في نهاية العام. ولكن يمكنك متابعة المحتوى ومقاطع الفيديو ، فهي متاحة على Youtube.

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

  1. هيكل وتفسير برامج الكمبيوتر
  2. كيفية تصميم البرامج
  3. مفاهيم وتقنيات ونماذج البرمجة الحاسوبية


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

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

حظًا سعيدًا مع عامك الوظيفي الجديد!

Source: https://habr.com/ru/post/ar383551/


All Articles