سؤال

حسنًا، لقد أدركت أن F# قادر على إدارة المراجع (نوع من المراجع مثل C++).يتيح ذلك إمكانية تغيير قيمة المعلمات التي تم تمريرها في الوظائف كما يمكّن المبرمج من إرجاع أكثر من قيمة واحدة.ولكن إليك ما أحتاج إلى معرفته:

  1. الكلمة المفتاحية المرجعية:الكلمة الرئيسية ref يتم استخدامه لإنشاء مرجع من قيمة إلى تلك القيمة من النوع المستنتج.لذا

    let myref = ref 10
    

    هذا يعني أن F# سيقوم بإنشاء كائن من النوع Ref<int> وضع هناك (في الحقل القابل للتغيير) my int 10.

    نعم.لذلك أفترض ذلك ref يتم استخدامه لإنشاء مثيلات Ref<'a> يكتب.هل هذا صحيح؟

  2. قيمة الوصول:من أجل الوصول إلى القيمة المخزنة في المرجع يمكنني القيام بذلك:

    let myref = ref 10
    let myval = myref.Value
    let myval2 = !myref
    

    بينما ال := يتيح لي عامل التشغيل فقط تعديل القيمة مثل هذا:

    let myref = ref 10
    myref.Value <- 30
    myref := 40
    

    لذا ! (بانغ) يتجاهل مرجعي.و := تحريره.وأفترض أن هذا صحيح أيضا.

  3. & المشغل:ماذا يفعل هذا المشغل؟هل سيتم تطبيقه على نوع مرجعي؟لا، أعتقد أنه يجب تطبيقه على قيمة قابلة للتغيير وهذا ما يُرجعه؟المرجع؟العنوان؟في حالة استخدام التفاعلية:

    let mutable mutvar = 10;;
    &a;;
    

    السطر الأخير يلقي خطأ لذلك لا أفهم ما هو & المشغل هو ل.

  4. بواسطةالمرجع:ماذا عن byref؟هذا مهم جدًا بالنسبة لي، لكنني أدرك أنني لا أفهمه.أفهم أنه يتم استخدامه في الوظيفة المتعلقة بتمرير المعلمة.يستخدم المرء byref عندما يريد إمكانية تحرير القيمة التي تم تمريرها (وهذا يتعارض قليلاً مع فلسفة اللغات الوظيفية ولكن f# شيء أكثر من ذلك).خذ بعين الاعتبار ما يلي:

    let myfunc (x: int byref) =
        x <- x + 10
    

    هذا غريب.وأنا أعلم أنه إذا كان لديك مرجع let myref = ref 10 ثم قم بذلك لتحرير القيمة: myref <- 10 ينشأ خطأ لأنه يجب أن يكون مثل هذا: myref := 10.ومع ذلك، فإن حقيقة أنه في تلك الوظيفة يمكنني تحريرها x باستخدام <- المشغل يعني ذلك x ليس مرجعا، أليس كذلك؟

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

  5. وظائف الاتصال:كيف يمكنني استخدام وظيفة باستخدام معلمات byref؟

    ال & المشغل متورط ولكن هل يمكنك شرح ذلك بشكل أفضل من فضلك؟في هذه المقالة: معلمات ووسائط MSDN يتم توفير المثال التالي:

    type Incrementor(z) =
        member this.Increment(i : int byref) =
           i <- i + z
    
    let incrementor = new Incrementor(1)
    let mutable x = 10
    // A: Not recommended: Does not actually increment the variable. (Me: why?)
    incrementor.Increment(ref x)
    // Prints 10.
    printfn "%d" x  
    
    let mutable y = 10
    incrementor.Increment(&y) (* Me: & what does it return? *)
    // Prints 11.
    printfn "%d" y 
    
    let refInt = ref 10
    incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *)
    // Prints 11.
    printfn "%d" !refInt
    
هل كانت مفيدة؟

المحلول

المرجع الكلمة الأساسية نعم عندما تكتب let a = ref 10 أنت تكتب بشكل أساسي let a = new Ref<int>(10) أين ال Ref<T> النوع يحتوي على حقل قابل للتغيير Value.

قيمة الوصول ال := و ! العوامل هي مجرد اختصارات للكتابة:

a.Value <- 10  // same as writing: a := 10
a.Value        // same as writing: !a

بواسطةالمرجع هو نوع خاص يمكن استخدامه (بشكل معقول) فقط في معلمات الطريقة.وهذا يعني أن الوسيطة يجب أن تكون في الأساس مؤشرًا لبعض مواقع الذاكرة (المخصصة على الكومة أو المكدس).إنه يتوافق مع out و ref المعدلات في C#.لاحظ أنه لا يمكنك إنشاء متغير محلي من هذا النوع.

& المشغل هي طريقة لإنشاء قيمة (مؤشر) يمكن تمريرها كوسيطة إلى دالة/طريقة تتوقع byref يكتب.

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

ما يلي لا يعمل:

let a = 10            // Note: You don't even need 'mutable' here
bar.Increment(ref a)  

والسبب هو أنك تقوم بإنشاء مثيل جديد لـ Ref<int> وأنت تقوم بنسخ قيمة a في هذه الحالة.ال Increment تقوم الطريقة بعد ذلك بتعديل القيمة المخزنة على الكومة في مثيل Ref<int>, ، لكن لم تعد لديك إشارة إلى هذا الكائن بعد الآن.

let a = ref 10
bar.Increment(a)  

هذا يعمل، لأن a هي قيمة النوع Ref<int> وتقوم بتمرير مؤشر إلى المثيل المخصص للكومة Increment ثم احصل على القيمة من الخلية المرجعية المخصصة للكومة باستخدام !a.

(يمكنك استخدام القيم التي تم إنشاؤها باستخدام ref كحجج ل byref نظرًا لأن المترجم يتعامل مع هذه الحالة بشكل خاص - فسوف يشير تلقائيًا إلى ملف Value الحقل لأن هذا سيناريو مفيد...).

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