مرجع خلايا (F#)

مرجع خلايا are تخزين مواقع? that تمكين you إلى إنشاء mutable قيم مع مرجع semantics.

ref expression

ملاحظات

You استخدم the ref عامل قبل a القيمة إلى إنشاء a جديد مرجع خلية that encapsulates the القيمة. You can then تغيير the underlying القيمة because it هو mutable.

A مرجع خلية holds an الفعلي القيمة; it ليس just an العنوان. When you إنشاء a مرجع خلية بواسطة using the ref عامل, you إنشاء a نسخ of the underlying القيمة كـ an encapsulated mutable القيمة.

You can عدم مرجعية a مرجع خلية بواسطة using the ! (bang) عامل.

The following تعليمات برمجية مثال illustrates the إعلان و استخدم of مرجع خلايا.

// Declare a reference.
let refVar = ref 6

// Change the value referred to by the reference.
refVar := 50

// Dereference by using the ! operator.
printfn "%d" !refVar

المخرج هو 50.

مرجع خلايا are instances of the Ref generic سجل نوع, which هو declared كـ follows.

type Ref<'a> =
    { mutable contents: 'a }

The نوع 'a ref هو a مرادف for Ref<'a>. The compiler و IntelliSense في the IDE عرض the former for this نوع, but the underlying تعريف هو the latter.

The ref عامل creates a جديد مرجع خلية. التعليمة البرمجية التالية هو التعريف refعامل التشغيل.

let ref x = { contents = x }

يعرض الجدول التالي الميزات التي تتوفر في مرجع خلية.

عامل تشغيل أو عضو لحقل

الوصف

Type

التعريف

!(عدم مرجعية عامل التشغيل)

إرجاع القيمة الأساسية.

'a ref -> 'a

let (!) r = r.contents

:=(عامل التعيين)

قم بتغيير القيمة الأساسية.

'a ref -> 'a -> unit

let (:=) r x = r.contents <- x

ref(عامل)

قم بتغليف القيمة في خلية مرجع جديد.

'a -> 'a ref

let ref x = { contents = x }

Value(خاصية)

الحصول أو قم بتعيين القيمة الأساسية.

unit -> 'a

member x.Value = x.contents

contents(حقل السجل)

الحصول أو قم بتعيين القيمة الأساسية.

'a

let ref x = { contents = x }

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

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

let xRef : int ref = ref 10

printfn "%d" (xRef.Value)
printfn "%d" (xRef.contents)

xRef.Value <- 11
printfn "%d" (xRef.Value)
xRef.contents <- 12
printfn "%d" (xRef.contents)

الإخراج هو كما يلي.

10
10
11
12

حقل contentsهو المتوفرة من أجل التوافق مع الإصدارات الأخرى من ML وسوف تعطي تحذير أثناء التحويل البرمجي. إلى تعطيل التحذير، استخدم --mlcompatibilityخيار المترجم. لمزيد من المعلومات، راجع خيارات برنامج التحويل البرمجي (F #).

مثال

يلي تعليمات برمجية يوضح استخدام مرجع خلايا في تمرير معلمة. Incrementorيحتوي النوع على أسلوب Incrementالتي تأخذ معلمة يتضمن byrefفي نوع المعلمة. byrefفي نوع معلمة يشير إلى أن المتصلين يجب تمرير مرجع خلية أو العنوان نموذجي متغير من النوع المحدد، في هذه الحالة int. المتبقي تعليمات برمجية يوضح كيفية استدعاء Incrementمع كل من هذه الأنواع من الوسيطات، ويظهر استخدم refالعامل تشغيل متغير لإنشاء مرجع خلية ( ref myDelta1). ثم يظهر استخدام العنوان-operaإلىr ( &) إلى إنشاء على وسيطة المناسبة. وأخيراً، Incrementأسلوب هو يسمى مرة أخرى عن طريق استخدام مرجع بالخلية التي هو التصريح باستخدام letربط. يوضح السطر الأخير من تعليمات برمجية الاستخدام !operaإلىr إلى عدم مرجعية مرجع خلية للطباعة.

type Incrementor(delta) =
    member this.Increment(i : int byref) =
        i <- i + delta

let incrementor = new Incrementor(1)
let mutable myDelta1 = 10
incrementor.Increment(ref myDelta1)
// Prints 10:
printfn "%d" myDelta1  

let mutable myDelta2 = 10
incrementor.Increment(&myDelta2)
// Prints 11:
printfn "%d" myDelta2 

let refInt = ref 10
incrementor.Increment(refInt)
// Prints 11:
printfn "%d" !refInt

لمزيد من المعلومات حول كيفية تمرير مرجع، راجع معلمات و وسيطات (F#).

ملاحظة

يجب أن تعرف المبرمجين C# ذلك refيعمل بشكل مختلف في F# أكثر في C#. على سبيل المثال، استخدم refعند pكـs وسيطة ليس له نفس التأثير في F# كـ يتم في C#‎.

أو مرجع لخلايا.Mutable متغيرات

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

يوضح مثال التعليمة البرمجية التالية سيناريو حيث يجب استخدام مرجع خلية.

// Print all the lines read in from the console.
let PrintLines1() =
    let mutable finished = false
    while not finished do
        match System.Console.ReadLine() with
        | null -> finished <- true
        | s -> printfn "line is: %s" s


// Attempt to wrap the printing loop into a 
// sequence expression to delay the computation.
let PrintLines2() =
    seq {
        let mutable finished = false
        // Compiler error:
        while not finished do  
            match System.Console.ReadLine() with
            | null -> finished <- true
            | s -> yield s
    }

// You must use a reference cell instead.
let PrintLines3() =
    seq {
        let finished = ref false
        while not !finished do
            match System.Console.ReadLine() with
            | null -> finished := true
            | s -> yield s
    }

في the السابق تعليمات برمجية, the مرجع خلية finished هو مُضمن في محلي الولاية, that هو, متغيرات that are في the closure are تاريخ الإنشاء و used entirely within the تعبير, في this حالة a تسلسل تعبير. Consider what occurs when the متغيرات are non-محلي. Closures can also الوصول non-محلي الولاية, but when this occurs, the متغيرات are copied و stored بواسطة القيمة. This عملية هو known كـ القيمة semantics. This means that the قيم at the الوقت of the نسخ are stored, و أي subsequent التغييرات إلى the متغيرات are not reflected. If you want إلى مقطع صوتي the التغييرات of non-محلي متغيرات, أو, في غير ذلك الكلمات, if you need a closure that interacts مع non-محلي الولاية بواسطة using مرجع semantics, you must استخدم a مرجع خلية.

The following تعليمات برمجية أمثلة demonstrate the استخدم of مرجع خلايا في closures. في this حالة, the closure نتائج من the جزئي تطبيق of دالة الوسيطات.

// The following code demonstrates the use of reference
// cells to enable partially applied arguments to be changed
// by later code.

let increment1 delta number = number + delta

let mutable myMutableIncrement = 10

// Closures created by partial application and literals.
let incrementBy1 = increment1 1
let incrementBy2 = increment1 2

// Partial application of one argument from a mutable variable.
let incrementMutable = increment1 myMutableIncrement

myMutableIncrement <- 12

// This line prints 110.
printfn "%d" (incrementMutable 100)

let myRefIncrement = ref 10

// Partial application of one argument, dereferenced
// from a reference cell.
let incrementRef = increment1 !myRefIncrement

myRefIncrement := 12

// This line also prints 110.
printfn "%d" (incrementRef 100)

// Reset the value of the reference cell.
myRefIncrement := 10

// New increment function takes a reference cell.
let increment2 delta number = number + !delta

// Partial application of one argument, passing a reference cell
// without dereferencing first.
let incrementRef2 = increment2 myRefIncrement

myRefIncrement := 12

// This line prints 112.
printfn "%d" (incrementRef2 100)

راجع أيضًا:

المرجع

الرمز وعامل التشغيل مرجع (F#)

المبادئ

معلمات و وسيطات (F#)

موارد أخرى

مرجع لغة ب #