Başvuru Hücreleri (F#)
Başvuru hücreleri, başvuru semantiğiyle değişebilir değerler oluşturmanıza olanak sağlayan depolama yerleridir.
ref expression
Notlar
Değeri kapsülleyen yeni bir başvuru hücresi oluşturmak için bir değerden önce ref işlecini kullanırsınız.Ardından, temeldeki değer değişebilir olduğundan değiştirebilirsiniz.
Başvuru hücresi gerçek bir değer taşır; yalnızca adres değildir.ref işlecini kullanarak bir başvuru hücresi oluşturduğunuzda, saklanmış değişebilir bir değer olarak temeldeki değerin bir kopyasını oluşturmuş olursunuz.
! (bang) işlecini kullanarak bir başvuru hücresine başvurabilirsiniz.
Aşağıdaki kod örneği başvuru hücrelerinin bildirim ve kullanımını göstermektedir.
// 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
Çıktı şu şekildedir: 50.
Referans hücreleri aşağıdaki gibi tanımlanmış olan Ref genel kayıt türünün örnekleridir.
type Ref<'a> =
{ mutable contents: 'a }
'a ref türü Ref<'a> ile eşanlamlıdır.Derleyici ve IDE içindeki IntelliSense, bu tür için ilkini görüntüler fakat temeldeki tanım ikincisidir.
ref işleci yeni bir başvuru hücresi oluşturur.Aşağıdaki kod ref işlecinin bildirimidir.
let ref x = { contents = x }
Aşağıdaki tablo başvuru hücresindeki mevcut özellikleri göstermektedir.
İşleç, üye veya alan |
Açıklama |
Tür |
Tanım |
---|---|---|---|
! (başvuru işleci) |
Temeldeki değeri döndürür. |
'a ref -> 'a |
let (!) r = r.contents |
:= (atama işleci) |
Temeldeki değeri değiştirir. |
'a ref -> 'a -> unit |
let (:=) r x = r.contents <- x |
ref (işleç) |
Yeni bir başvuru hücresine bir değer kapsüller. |
'a -> 'a ref |
let ref x = { contents = x } |
Value (özellik) |
Temeldeki değeri alır veya ayarlar. |
unit -> 'a |
member x.Value = x.contents |
contents (kayıt alanı) |
Temeldeki değeri alır veya ayarlar. |
'a |
let ref x = { contents = x } |
Temeldeki değere erişmek için çeşitli yollar vardır.Başvuru işleci (!) tarafından döndürülen değer, atanabilir bir değer değildir.Bu nedenle, temeldeki değeri değiştiriyorsanız, onun yerine (:=) atama işlecini kullanmanız gerekir.
Hem Value özelliği, hem de contents alanı atanabilir değerlerdir.Bu nedenle, bunları temeldeki değere ulaşmak ya da onu değiştirmek için aşağıdaki kodda gösterildiği gibi kullanabilirsiniz.
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)
Çıktı aşağıdaki gibidir:
10
10
11
12
contents alanı diğer ML sürümleriyle uyumluluk için sağlanır ve derleme sırasında bir uyarı verecektir.Uyarıyı devre dışı bırakmak için --mlcompatibility derleyici seçeneğini kullanın.Daha fazla bilgi için bkz. Derleyici Seçenekleri (F#).
Örnek
Aşağıdaki kod, başvuru hücrelerinin parametre geçişlerinde kullanımını örneklendirmektedir.Incrementor türü, Increment yöntemine sahiptir. Bu yöntem, parametre türünde byref içeren bir parametre alır.Parametre türündeki byref, arayanların bir başvuru hücresini veya belirtilen türün tipik değişkenin adresini, bu durumda int'yi, geçmesi gerektiğini gösterir.Geri kalan kod, her iki bağımsız değişken türüyle Increment'in nasıl aranacağını ve ref işlecinin (ref myDelta1) başvuru hücresini oluşturmak için bir değişken üzerinde nasıl kullanılacağını gösterir.Ardından, (&) işleç adresinin uygun bir bağımsız değişken oluşturmak için kullanımını gösterir.Son olarak, Increment yöntemi bir let bağlama kullanılarak bildirilen bir başvuru yöntemi kullanılarak çağrılır.Kodun son satırı, yazdırma için başvuru hücresine başvuran ! işlecinin kullanımını gösterir.
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
Başvuruyu nasıl geçeceğiniz hakkında daha fazla bilgi için bkz. Parametreler ve Bağımsız Değişkenler (F#).
[!NOT]
C# programcıları, ref'in F#'ta C#'tan farklı çalıştığını bilmelidir.Örneğin, bir bağımsız değişkeni geçtiğinizde ref kullanımı, C#'ta gösterdiği etkiyi F#'ta göstermez.
Başvuru Hücreleri ve Değişebilir Değişkenleri Karşılaştırma
Başvuru hücreleri ve değişebilir değişkenler genellikle aynı durumlarda kullanılabilir.Ancak, bazı durumlarda değişebilir değişkenler kullanılamaz ve bunun yerine bir başvuru hücresi kullanmanız gerekir.Genel olarak, derleyici tarafından kabul edilen yerlerde değişebilir değişkenleri tercih etmelisiniz.Ancak derleyici, kapanışları oluşturan ifadelerde değişebilir değişkenleri kullanamayacağınızı bildirecektir.Kapanışlar lambda ifadeleri, dizi ifadeleri, hesaplama ifadeleri gibi belirli F# ifadeleri tarafından oluşturulan yerel işlevler ve kısmen uygulanan bağımsız değişkenler kullanan curry biçimli işlevlerdir.Bu ifadeler tarafından üretilen kapanışlar daha sonra değerlendirmek üzere saklanır.Bu işlem değişebilir değişkenlerle uyumlu değildir.Bu nedenle, böyle bir ifadede değişebilir durum gerekirse, başvuru hücrelerini kullanmanız gerekir.Kapanışlar hakkında daha fazla bilgi için bkz: Kapanışlar (F#).
Aşağıdaki kod örneği, başvuru hücresi kullanmanız gereken senaryoyu göstermektedir.
// 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
}
Bir önceki kodda, finished başvuru hücresi yerel duruma, yani bu durumda bir sıralama ifadesi olan, ifade içinde oluşturulan ve tamamen kullanılan kapanıştaki değişkenlere dahil edilmiştir.Değişkenler yerel olmadığında ne olacağını göz önünde bulundurun.Kapanışlar ayrıca yerel olmayan duruma da erişebilir, ancak böyle bir durumda, değişkenler kopyalanır ve değer tarafından depolanır.Bu işlem değer semantiği olarak bilinir.Bu, kopyalama anındaki değerlerin depolandığı ve değişkenlere yapılan sonraki değişikliklerin yansıtılmadığı anlamına gelir.Yerel olmayan değişkenlere yapılan değişiklikleri takip etmek isterseniz veya diğer bir deyişle başvuru semantiği kullanarak yerel olmayan durumla etkileşime giren bir kapanış gerekirse, başvuru hücresi kullanmanız gerekir.
Aşağıdaki kod örnekleri başvuru hücrelerinin kapanışlarda kullanımını örneklendirmektedir.Bu durumda kapanış, işlev bağımsız değişkenlerinin kısmi uygulamasından kaynaklanır.
// 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)
Ayrıca bkz.
Başvuru
Kavramlar
Parametreler ve Bağımsız Değişkenler (F#)