سؤال

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

  • ما هي وظيفة متداخلة؟
  • لماذا؟!؟
  • ما الذي يمكنك فعله بوظيفة متداخلة لا يمكنك القيام بها بأي طريقة أخرى؟
  • ماذا يمكنك أن تفعل بوظيفة متداخلة صعبة أو غير أنيقة بدون وظائف متداخلة؟

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

هل للوظائف المتداخلة نطاق (بشكل عام، أفترض أن اللغات تختلف في هذا) تمامًا كما أن المتغيرات داخل الوظيفة لها نطاق؟

الرجاء إضافة اللغة التي تشير إليها إذا لم تكن متأكدًا من أن إجابتك غير محددة للغة.

-آدم

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

المحلول

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

(define (make-counter)
  (let ((count 0))                ; used to store the count
    (define (counter)             ; this is the counter we're creating
      (set! count (+ count 1))    ; increment the count
      count)                      ; return the new count
    counter))                     ; return the new counter function

(define mycounter (make-counter)) ; create a counter called mycounter

(mycounter)                       ; returns 1

(mycounter)                       ; returns 2

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

(define mycounter2 (make-counter))

(mycounter2)                      ; returns 1

(mycounter)                       ; returns 3

نصائح أخرى

إنه مفيد للتكرار عندما يكون هناك طريقة واحدة فقط ستستدعيه

string[] GetFiles(string path)
{
  void NestedGetFiles(string path, List<string> result)
  {
    result.AddRange( files in the current path);
    foreach(string subPath in FoldersInTheCurrentPath)
      NestedGetFiles(subPath, result);
  }

   List<string> result = new List<string>();
   NestedGetFiles(path, result);
   return result.ToArray();
}

الكود أعلاه مكون بالكامل ولكنه يعتمد على C# لإعطاء فكرة عما أعنيه.الطريقة الوحيدة التي يمكنها استدعاء NestedGetFiles هي طريقة GetFiles.

الوظيفة المتداخلة هي مجرد وظيفة داخل وظيفة أخرى.

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

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

حالة الاستخدام الشائعة بالنسبة لي هي عندما تؤدي الوظيفة الكثير من المنطق المعقد ولكن ما تحسبه/ترجعه الوظيفة يسهل تجريده لجميع الحالات التي يمليها المنطق.

(ج#):أستخدم ذلك لتبسيط عرض Object Browser ولتنظيم فصولي بشكل أفضل.كعجلة فئة متداخلة في فئة الشاحنة.

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

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

int doStuff() {
    int result;
    void cleanUpReturn() {
        myResource1.release();
        myResource2.release();
        return result * 2 + 1;
    }

    auto myResource1 = getSomeResource();
    auto myResource2 = getSomeOtherResource();
    if(someCondition) {
        return cleanUpReturn();
    } else {
        doSomeOtherStuff();
        return cleanUpReturn();
    }
}

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

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

>>> def GetIntMaker(x):
...   def GetInt():
...     return x
...   return GetInt
... 
>>> GetInt = GetIntMaker(1)
>>> GetInt()
1

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

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

function process(qryResult q1, qryResult q2) {

   object o;
   if (q1.someprop == "useme") {
       o.prop1 = q1.prop1;
       o.prop2 = q1.prop2;
       o.prop3 = q1.prop3;
   } else if (q2.someprop == "useme") {
       o.prop1 = q2.prop1;
       o.prop2 = q2.prop2;
       o.prop3 = q2.prop3;
   }

   return o;

}

إذا كان لديك 20 خاصية، فأنت تكرر الكود لتعيين الكائن مرارًا وتكرارًا مما يؤدي إلى وظيفة ضخمة.يمكنك إضافة دالة متداخلة بسيطة لنسخ الخصائص من الاستعلام إلى الكائن.مثله:

function process(qryResult q1, qryResult q2) {

   object o;
   if (q1.someprop == "useme") {
       fillObject(o,q1);
   } else if (q2.someprop == "useme") {
       fillObject(o,q2);
   }

   return o;

   function fillObject(object o, qryResult q) {
       o.prop1 = q.prop1;
       o.prop2 = q.prop2;
       o.prop3 = q.prop3;
   }


}

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

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