Odkaz na buňky (F#)
Odkazovat na buňky jsou umístění úložiště, které umožňují vytvořit odkaz sémantiku proměnlivých hodnot.
ref expression
Poznámky
Použití ref operátor před hodnotu vytvořit odkaz na buňky zapouzdří hodnotu.Potom můžete změnit základní hodnota je proměnlivých.
Odkaz na buňku obsahuje skutečné hodnoty; není pouze adresu.Pokud vytvoříte odkaz na buňku pomocí ref operátor, vytvořit kopii jako zapouzdřená proměnlivých hodnota zadaná hodnota.
Je zrušit reference můžete struktury odkaz na buňku pomocí ! operátor (vykřičník).
Následující příklad kódu ukazuje, prohlášení a použijte odkaz na buňky.
// 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
Výstup je 50.
Odkaz na buňky jsou instance Ref záznam obecný typ, který je deklarován takto.
type Ref<'a> =
{ mutable contents: 'a }
Typ 'a ref je synonymum pro Ref<'a>.Kompilátor a technologie IntelliSense v IDE zobrazení bývalé pro tento typ, ale je ten základní definice.
ref Operátor vytvoří novou buňku odkaz.Následující kód je prohlášení ref operátor.
let ref x = { contents = x }
Následující tabulka obsahuje funkce, které jsou k dispozici v referenční kyvetě.
Operátor, člen nebo pole |
Description |
Type |
Definice |
---|---|---|---|
!(zrušit reference struktury operátor) |
Vrátí hodnotu základní. |
'a ref -> 'a |
let (!) r = r.contents |
:=(operátor přiřazení) |
Zadaná hodnota se změní. |
'a ref -> 'a -> unit |
let (:=) r x = r.contents <- x |
ref(operátor) |
Zapouzdřuje hodnotu do buňky nový odkaz. |
'a -> 'a ref |
let ref x = { contents = x } |
Value(vlastnost) |
Získá nebo nastaví zadaná hodnota. |
unit -> 'a |
member x.Value = x.contents |
contents(pole záznamu) |
Získá nebo nastaví zadaná hodnota. |
'a |
let ref x = { contents = x } |
Přístup k podkladové hodnoty několika způsoby.Hodnota vrácená operátorem dereference (!) není přiřadit hodnotu.Proto pokud upravujete podkladové hodnoty, musíte použít operátor přiřazení (:=) místo.
I Value vlastnost a contents pole jsou přiřadit hodnoty.Proto můžete tyto přístup nebo změnit základní hodnoty, jak je znázorněno v následujícím kódu.
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)
Výstup je takto.
10
10
11
12
Pole contents je zajištěna kompatibilita s jinými verzemi ML a ohlásí varování během kompilace.Chcete-li zakázat upozornění, použijte --mlcompatibility volba kompilátoru.Další informace naleznete v tématu Volby kompilátoru (F#).
Příklad
Následující kód ilustruje použití odkaz na buňky v předávání parametrů.Incrementor Typu má metodu Increment , která má parametr, který zahrnuje byref v typu parametru.byref v parametru typ označuje, že volající musí projít odkaz na buňku nebo adresu typické zadaného typu proměnné v tomto případě int.Zbývající kód ukazuje, jak volat Increment s oběma typy argumentů a znázorňuje použití ref operátor na proměnnou vytvoříte odkaz na buňku (ref myDelta1).Potom zobrazí použití operátoru adresu z (&) generovat odpovídající argument.Nakonec Increment je volána metoda znovu pomocí odkaz na buňku, která je deklarována pomocí let vazby.Poslední řádek kódu ukazuje použití ! operátor zrušit reference struktury odkaz na buňku pro tisk.
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
Další informace o tom, odkazem naleznete Parametry a argumenty (F#).
[!POZNÁMKA]
C# programátoři by měla vědět, že ref F# funguje jinak, než v jazyce C#.Například použití ref při předání argument nemá stejný efekt v F# jako v C#.
Odkazy na buňky vs.Proměnlivých proměnné
Odkaz na buňky a proměnlivých proměnných lze často používají ve stejných situacích.Existují však některé situace, ve kterých nelze použít proměnné proměnlivých a místo toho je třeba použít odkaz na buňku.Obecně by raději proměnlivých proměnných, pokud jsou přijaty kompilátorem.Však ve výrazech, které generují uzávěry, Kompilátor nahlásí proměnlivých proměnné nelze použít.Uzávěry jsou místní funkce, které jsou generovány určitých F# výrazy, například lambda výrazů, sekvence výrazů, výpočet výrazy a curried funkce, které používají částečně použity argumenty.Uzávěry generovaných tyto výrazy jsou uloženy pro pozdější vyhodnocení.Tento proces není kompatibilní s proměnlivých proměnné.Proto pokud potřebujete proměnlivých stát takový výraz, musíte použít odkaz na buňky.Další informace o uzavření viz uzávěry (F#).
Následující příklad kódu ukazuje scénář, ve kterém je nutné použít odkaz na buňku.
// 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
}
V předchozím kódu, odkaz na buňku finished je zahrnut v místním stavu, proměnné, které jsou v uzavření jsou vytvořeny a používány zcela ve výrazu, v tomto případě výraz sekvence.Zvažte, co dojde k proměnné je přesměrovat.Uzávěry také přístup k-local státu, ale v takovém případě jsou zkopírovány a uložené hodnoty proměnných.Tento proces je znám jako hodnotu sémantiku.To znamená, že hodnoty v době kopie jsou uloženy a proměnných pozdější změny se neprojeví.Chcete-li sledovat změny proměnných, které nejsou místní, nebo v jiných slov, pokud potřebujete uzavření, která spolupracuje s-local stavu pomocí odkaz sémantiku, musíte použít odkaz na buňku.
Následující příklady kódu ukazují použití odkaz na buňky v uzavřené.V případě uzavření výsledků z částečné uplatnění argumenty funkce.
// 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)
Viz také
Referenční dokumentace
Referenční operátor (F#) a symbol