Odwoływanie się do komórek (F#)
Odwołuje się do komórek są lokalizacji przechowywania, które umożliwiają utworzenie tych wartości z semantyką odniesienia.
ref expression
Uwagi
Za pomocą ref operatora przed wartość, aby utworzyć nowe komórki odniesienia, która hermetyzuje wartość.Następnie można zmienić wartości podstawowej, ponieważ mutable.
Komórka odniesienia przechowuje wartość rzeczywistą; nie jest tylko adres.Podczas tworzenia komórki odwołanie za pomocą ref operatora, utworzyć kopię jako encapsulated wartości dla tych wartości podstawowej.
Cofnięcia odwołania komórek odniesienia przy użyciu ! (wykrzyknika).
Poniższy przykład kodu ilustruje deklarację i użyj odwołania komórek.
// 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
Dane wyjściowe są 50.
Odwoływanie się do komórek są instancjami Ref typ rodzajowy rekordu, która jest zadeklarowana w następujący sposób.
type Ref<'a> =
{ mutable contents: 'a }
Typ 'a ref jest synonimem dla Ref<'a>.Kompilator i technologii IntelliSense w IDE wyświetlają Byłej dla tego typu, ale ten ostatni jest definicja podstawowych.
ref Operator tworzy nowe komórki odwołanie.Poniższy kod jest deklaracja z ref operatora.
let ref x = { contents = x }
W poniższej tabeli przedstawiono funkcje, które są dostępne w komórce odniesienia.
Operator, członka lub pola |
Opis |
Typ |
Definicja |
---|---|---|---|
!(operator nieprawidłowego) |
Zwraca wartości podstawowej. |
'a ref -> 'a |
let (!) r = r.contents |
:=(operator przypisania) |
Zmiany wartości podstawowej. |
'a ref -> 'a -> unit |
let (:=) r x = r.contents <- x |
ref(operator) |
Hermetyzuje wartość do nowej komórki odwołanie. |
'a -> 'a ref |
let ref x = { contents = x } |
Value(właściwość) |
Zwraca lub ustawia wartość podstawowej. |
unit -> 'a |
member x.Value = x.contents |
contents(pola rekordu) |
Zwraca lub ustawia wartość podstawowej. |
'a |
let ref x = { contents = x } |
Do uzyskania dostępu do podstawowych wartości na kilka sposobów.Wartość zwracana przez dereference operator (!) nie jest możliwa do przypisania wartości.W związku z tym, w przypadku modyfikowania wartości podstawowej, należy użyć operatora przypisania (:=) zamiast.
Obie Value właściwości i contents pole to można przypisać wartości.W związku z tym można te dostępu albo zmienić wartości podstawowej, jak pokazano w poniższym kodzie.
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)
Wprowadza dane wyjściowe.
10
10
11
12
Pole contents zapewnia zgodnooć z innymi wersjami ML i wygeneruje ostrzeżenie podczas kompilacji.Aby wyłączyć ostrzeżenia, należy użyć --mlcompatibility opcję kompilatora.Aby uzyskać więcej informacji, zobacz Opcje kompilatora (F#).
Przykład
Poniższy kod ilustruje wykorzystanie Ogniwa wzorcowe w parametrze, przekazując.Incrementor Typu ma metodę Increment pobierająca parametr, który zawiera byref w polu Typ parametru.byref w parametrze typu wskazuje, że wywołujący musi minąć komórki odwołanie lub adres typowe zmienną określonego typu, w tym przypadku int.Pozostały kod ilustruje sposób wywołania Increment z obu tych typów argumentów i przedstawia zastosowanie ref operatora na zmienną do utworzenia komórki odniesienia (ref myDelta1).Następnie prezentuje ono sposób użycia operatora z adresu (&) do generowania odpowiednich argument.Wreszcie Increment wywoływana jest metoda ponownie za pomocą komórki odniesienia, która jest zadeklarowana za pomocą let powiązania.Ostatnia linia kodu ilustruje użycie ! operatora do cofnięcia odwołania do komórki odwołanie do drukowania.
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
Aby uzyskać więcej informacji na temat przechodzą przez odwołanie, zobacz Parametry i argumenty (F#).
[!UWAGA]
Programistów języka C# należy wiedzieć, że ref działa w F# inaczej, niż w języku C#.Na przykład, użycie ref po przesunięciu argument nie ma ten sam efekt w F# jak w języku C#.
Odwołanie komórki vs.Tych zmiennych.
Odwoływanie się do komórek i tych zmiennych można często używane w tej samej sytuacji.Istnieją jednak pewne sytuacje, w których nie można używać tych zmiennych i komórki odniesienia należy użyć zamiast.Ogólnie rzecz biorąc należy preferować tych zmiennych, gdzie są akceptowane przez kompilator.Jednak w wyrażeniach, które generują zamknięcia, kompilator będzie sprawozdanie, że nie można użyć tych zmiennych.Zamknięcia są lokalne funkcje, które są generowane przez niektórych F# wyrażeń, takich jak lambda wyrażenia, sekwencji wyrażeń, wyrażenia obliczeń i curried funkcji, które używają częściowo stosowane argumentów.Wolnych od pracy, generowane przez te wyrażenia są przechowywane dla późniejszej ocenie.Proces ten nie jest zgodny z tych zmiennych.W związku z tym Jeśli potrzebujesz mutable Państwo w wyrażeniu jest, należy użyć odwołania komórek.Aby uzyskać więcej informacji na temat wolnych od pracy zobacz temat zamknięć (F#).
Poniższy przykład kodu pokazuje scenariusz, w którym należy użyć komórki odwołanie.
// 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
}
W poprzednim kodzie komórki odwołanie finished znajduje się w stanie lokalnych, oznacza to, zmienne, które znajdują się w zamknięcia są tworzone i używane wyłącznie w wyrażeniu, w tym przypadku wyrażenie sekwencji.Należy rozważyć, jakie występuje wówczas, gdy zmienne są nielokalnych.Wolnych od pracy można także uzyskać dostęp Państwo nielokalnych, ale w takim przypadku zmienne są kopiowane i przechowywane przez wartość.Proces ten jest znany jako semantykę wartości.Oznacza to, że wartości w czasie kopia są przechowywane i wszelkich późniejszych zmianach zmienne nie są uwzględniane.Jeśli chcesz śledzić zmiany — do lokalnych zmiennych, lub w innych wyrazów, jeśli potrzebujesz zamknięcia, który współdziała z Państwem do lokalnego przy użyciu odniesienia semantykę, należy użyć komórki odwołanie.
W poniższych przykładach kodu demonstrują użycie Ogniwa wzorcowe w wolnych od pracy.W przypadku zamknięcia wynika z częściowego stosowania argumenty funkcji.
// 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)
Zobacz też
Informacje
Symbol i Operator odniesienia (F#)