سؤال

في سنتي الثانية في الجامعة، "تعلمنا" لغة هاسكل، ولم أكن أعرف عنها شيئًا تقريبًا، بل وأقل من ذلك عن البرمجة الوظيفية.

ما هي البرمجة الوظيفية، ولماذا و/x أو أين أرغب في استخدامها بدلاً من البرمجة غير الوظيفية وهل أنا على صواب في الاعتقاد بأن لغة C هي لغة برمجة غير وظيفية؟

هل كانت مفيدة؟

المحلول

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

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

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

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

نصائح أخرى

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

هناك تعريفان مختلفان لـ "البرمجة الوظيفية" شائعة الاستخدام اليوم:

التعريف القديم (الناشئ من ليسب) هو أن البرمجة الوظيفية تدور حول البرمجة باستخدام وظائف من الدرجة الأولى، أي.حيث يتم التعامل مع الوظائف مثل أي قيمة أخرى حتى تتمكن من تمرير الوظائف كوسيطات إلى وظائف أخرى ويمكن للوظيفة إرجاع الوظائف بين قيم الإرجاع الخاصة بها.ويتوج هذا باستخدام وظائف ذات ترتيب أعلى مثل map و reduce (ربما سمعت عن mapReduce كعملية واحدة تستخدمها Google بكثافة، وليس من المستغرب أن تكون قريبة جدًا!).أنواع .NET System.Func و System.Action إتاحة وظائف ذات ترتيب أعلى في C#.على الرغم من أن الكاري غير عملي في C#، إلا أن الوظائف التي تقبل وظائف أخرى كوسيطات شائعة، على سبيل المثال.ال Parallel.For وظيفة.

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

أين أرغب في استخدامه بدلاً من البرمجة غير الوظيفية

في كل مكان.لقد أثبتت Lambdas في C# الآن فوائد كبيرة.يحتوي C++ 11 على لامدا.ليس هناك عذر لعدم استخدام وظائف ذات ترتيب أعلى الآن.إذا كان بإمكانك استخدام لغة مثل F# فسوف تستفيد أيضًا من استنتاج الكتابة والتعميم التلقائي والتطبيق الجزئي (بالإضافة إلى الكثير من ميزات اللغة الأخرى!).

هل أنا على حق في اعتقادي أن لغة C هي لغة برمجة غير وظيفية؟

نعم.C هي لغة إجرائية.ومع ذلك، يمكنك الحصول على بعض فوائد البرمجة الوظيفية باستخدام المؤشرات الوظيفية و void * شركة.

قد يكون من المفيد مراجعة هذه المقالة على ف # "101" على CoDe Mag نشرت مؤخرا.

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

أتمنى أن تجد هذه مفيدة :)

يحرر:

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

لا يُظهر رمز مثال John the Statistician البرمجة الوظيفية، لأنه عندما تقوم بالبرمجة الوظيفية، فإن المفتاح هو أن الكود لا يقوم بأي تعيينات ( record = thingConstructor(t) هي مهمة)، وليس لها أي آثار جانبية (localMap.put(record) هو عبارة ذات أثر جانبي).ونتيجة لهذين القيدين، كل ما أ وظيفة هل يتم التقاطه بالكامل من خلال الوسائط وقيمة الإرجاع الخاصة به.إعادة كتابة كود الإحصائي بالطريقة التي يجب أن يبدو بها، إذا كنت تريد محاكاة لغة وظيفية باستخدام C++:

RT getOrCreate(const T thing, 
                  const Function<RT<T>> thingConstructor, 
                  const Map<T,RT<T>> localMap) {
    return localMap.contains(t) ?
        localMap.get(t) :
        localMap.put(t,thingConstructor(t));
}

ونتيجة لقاعدة عدم وجود آثار جانبية، فإن كل عبارة هي جزء من القيمة المرجعة (وبالتالي return يأتي أولاً)، وكل عبارة عبارة عن تعبير.في اللغات التي تفرض البرمجة الوظيفية، فإن return الكلمة الأساسية ضمنية، و لو البيان يتصرف مثل C++ ?: المشغل أو العامل.

كما أن كل شيء غير قابل للتغيير، لذلك localMap.put لديه لإنشاء نسخة جديدة من localMap وإعادته، بدلاً من تعديل الأصل localMap, ، بالطريقة التي يعمل بها برنامج C++ أو Java العادي.اعتمادًا على بنية localMap، يمكن للنسخة إعادة استخدام المؤشرات في النسخة الأصلية، مما يقلل من كمية البيانات التي يجب نسخها.

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

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

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

تميل اللغات الوظيفية أيضًا إلى امتلاك بيئات تشغيل كبيرة جدًا.يعد Haskell استثناءً (الملفات التنفيذية GHC صغيرة تقريبًا مثل برامج C، سواء في وقت الترجمة أو وقت التشغيل)، لكن برامج SML، وCommon Lisp، وScheme تتطلب دائمًا الكثير من الذاكرة.

نعم أنت على صواب في اعتقادك أن لغة C هي لغة غير وظيفية.C هي لغة إجرائية.

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

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(t)) { return localMap.get(t); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t);
    localMap = localMap.put(t,record);
    return record; 
}

يحدث هذا في كثير من الأحيان.الآن، بلغة وظيفية أستطيع أن أكتب

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(t)) { return localMap.get(t); }
    RT<T> record = thingConstructor(t);
    localMap = localMap.put(t,record);
    return record; 
}

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

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(حيث * هو نوع من تدوين "اترك هذه المعلمة مفتوحة"، وهو نوع من الكاري)

ومن ثم فإن getOrCreate المحلي هو نفسه تمامًا كما لو كتبت كل شيء، في سطر واحد، دون أي تبعيات وراثة.

إذا كنت تبحث عن نص جيد على F#

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

تم تصميم F# على غرار OCaml لذا فإن أي نص OCaml سيساعدك على تعلم F# أيضًا.

وجدت ما هي البرمجة الوظيفية؟ ليكون مفيدا

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

تفضل صريحة when المعلمة

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

زيادة

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top