سؤال

أنا متجول في هذا الموقع قبل بضعة أيام على " العودية مجهول في ج#".فحوى المقال هو أن الكود التالي لن يعمل في ج#:

Func<int, int> fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

ثم تدخل المقالة في بعض التفاصيل حول كيفية الاستخدام الكاري و ال ص-كومبيناتور للعودة إلى "العودية المجهولة" في ج#.هذا مثير للاهتمام جدا ولكن مجمع صبي لبلدي الترميز اليومي أخشى.في هذه المرحلة على الأقل...

أحب أن أرى الأشياء لنفسي لذلك فتحت أحادية كشارب ريبل ودخلت هذا الخط.لا أخطاء.لذلك ، دخلت fib(8);.الكثير لدهشتي الكبيرة ، عملت!رد ريبل مرة أخرى مع 21!

اعتقدت ربما كان هذا بعض السحر مع ريبل ، لذلك أنا أطلقت المتابعة 'السادس' ، كتبته في البرنامج التالي ، وجمعت ذلك.

using System;

public class Program
{
    public static void Main(string[] args)
    {
        int x = int.Parse(args[0]);
        Func<int, int> fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;
        Console.WriteLine(fib(x));
    }
}

انها بنيت وركض تماما جدا!

أنا على تشغيل مونو 2.10 على ماك.ليس لدي الوصول إلى جهاز ويندوز الآن لذلك لا أستطيع اختبار هذا على صافي على ويندوز.

وقد تم إصلاح هذا على صافي كذلك أم أن هذه ميزة صامتة من مونو?المقال هو بضع سنوات من العمر.

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

تحديث:

مونو لا تفعل حقا" مجهول " العودية كما أنها تستخدم fib كمندوب اسمه.خطأي.حقيقة أن مونو ج # مترجم يفترض أ null قيمة ل fib قبل التعيين هو خطأ كما هو مذكور أدناه.أقول "مترجم" لأن صافي كلر تشغيل التجمع الناتج على ما يرام على الرغم من أن صافي ج# مترجم لن تجميع التعليمات البرمجية.

لجميع مقابلة النازيين هناك:

Func<int, int> fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

يمكن استبداله بنسخة تكرارية:

Func<int, int> fib = n => 
{
    int old = 1;
    int current = 1;
    int next;

    for (int i = 2; i < n; i++)
    {
        next = current + old;
        old = current;
        current = next;
    }
    return current;
};

قد ترغب في القيام بذلك لأن النسخة العودية غير فعالة في لغة مثل ج#.قد يقترح البعض استخدام المذكرة ولكن ، نظرا لأن هذا لا يزال أبطأ من الطريقة التكرارية ، فقد يكونون مجرد مغفلين.:-)

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

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

المحلول

هذا هو علة في مترجم أحادي.ينتهك القسم §12.3.3 من المواصفات.المتغير فيب لا يمكن استخدامها في مهيئ المتغير ، لأنه لم يتم تعيينه بالتأكيد.

نصائح أخرى

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

لمزيد من الأفكار حول هذه المسألة انظر مقالتي حول هذا الموضوع:

http://blogs.msdn.com/b/ericlippert/archive/2006/08/18/706398.aspx

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

جرب هذا...

Func<int, int> fib = null;
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n; 

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

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

تحقق من التسلسل التالي في مونو ج # ريبل:

csharp> Func<int, int> fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n; 
csharp> fibCopy = fib;
csharp> fib(6);
8
csharp> fibCopy(6);
8
csharp> fib = n => n * 2;
csharp> fib(6);
12
csharp> fibCopy(6);
18

هذا لأن:

fib = n => n * 2;
fibCopy = n > 1 ? fib(n - 1) + fib(n - 2) : n;

وبعبارة أخرى,

fibCopy = n > 1 ? (n - 1) * 2 + (n - 2) * 2 : n;    // at the moment

بوضوح, fibCopy يشير فقط إلى التعريف الحالي لـ fib (المندوب) وليس في حد ذاته.حتى مونو هو في الحقيقة مجرد ما قبل تعيين قيمة null إلى fib خلال المهمة الأولية بحيث تكون المهمة صالحة.

أنا أفضل كثيرا راحة عدم الاضطرار إلى الإعلان null لذلك أنا أحب هذا السلوك.ومع ذلك ، فإنه ليس حقا ما يتحدث عنه المقال الأصلي.

في مايكروسوفت ج # مترجم ، وسوف تعمل فقط إذا قمت بتعيين أول fib إلى null.

خلاف ذلك ، سوف يعطي خطأ لأن fib يستخدم قبل تعيينه.
مترجم مونو هو" ذكي " بما فيه الكفاية لتجنب هذا الخطأ (وبعبارة أخرى ، فإنه ينتهك المواصفات الرسمية)

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