Comprendre byref, ref et &
-
14-11-2019 - |
Question
Eh bien, j'ai compris que F# est capable de gérer les références (une sorte de références de type C++).Cela permet de modifier la valeur des paramètres transmis dans les fonctions et permet également au programmeur de renvoyer plus d'une seule valeur.Cependant, voici ce que je dois savoir :
Mot-clé de référence :Le mot clé
ref
est utilisé pour créer, à partir d'une valeur, une référence à cette valeur du type déduit.Donclet myref = ref 10
Cela signifie que F# créera un objet de type
Ref<int>
mettre là (dans le champ mutable) monint 10
.D'ACCORD.Donc je suppose que
ref
est utilisé pour créer des instances duRef<'a>
taper.Est-ce correct?Valeur d'accès :Afin d'accéder à une valeur stockée en référence, je peux faire ceci :
let myref = ref 10 let myval = myref.Value let myval2 = !myref
Tandis que le
:=
l'opérateur me permet simplement de modifier la valeur comme ceci :let myref = ref 10 myref.Value <- 30 myref := 40
Donc
!
(Bang) déréférence ma référence.Et:=
modifier.Je suppose que c'est correct aussi.L'opérateur:Que fait cet opérateur ?Doit-il être appliqué à un type référence ?Non, je suppose qu'il doit être appliqué à une valeur mutable et cela renvoie quoi ?Le référence?L'adresse?Si vous utilisez l'interactif :
let mutable mutvar = 10;; &a;;
La dernière ligne renvoie une erreur donc je ne comprends pas ce que
&
l'opérateur est pour.ParRéf :Qu'en est-il de
byref
?C'est très important pour moi, mais je réalise que je ne comprends pas.Je comprends qu'il est utilisé en fonction concernant le passage de paramètres.On utilise byref quand on veut que la valeur transmise puisse être modifiée (c'est un peu contraire à la philosophie des langages fonctionnels mais f# est quelque chose de plus que cela).Considérer ce qui suit:let myfunc (x: int byref) = x <- x + 10
Cela est étrange.Je sais que si tu as une référence
let myref = ref 10
puis faites ceci pour modifier la valeur :myref <- 10
une erreur se produit car cela devrait ressembler à ceci :myref := 10
.Cependant, le fait que dans cette fonction je puisse éditerx
en utilisant le<-
opérateur signifie quex
ce n'est pas une référence, non ?Si je suppose que
x
n'est pas une référence, alors je suppose aussi que, dans les fonctions, lors de l'utilisationbyref
sur un paramètre, la syntaxe mutable peut être appliquée à ce paramètre.C'est donc juste une question de syntaxe, si je suppose que tout va bien et, en fait, tout fonctionne (pas d'erreur de compilation).Cependant, qu'est-ce quex
?Fonctions d'appel :Comment puis-je utiliser une fonction utilisant les paramètres byref ?
Le
&
l'opérateur est impliqué, mais pourriez-vous mieux expliquer cela s'il vous plaît ?Dans cet article: Paramètres et arguments MSDN l'exemple suivant est fourni :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
La solution
Mot-clé de référence Oui, quand tu écris let a = ref 10
tu écris essentiellement let a = new Ref<int>(10)
où le Ref<T>
le type a un champ mutable Value
.
Valeur d'accès Le :=
et !
les opérateurs ne sont que des raccourcis pour écrire :
a.Value <- 10 // same as writing: a := 10
a.Value // same as writing: !a
ParRéf est un type spécial qui peut être (raisonnablement) utilisé uniquement dans les paramètres de méthode.Cela signifie que l'argument doit être essentiellement un pointeur vers un emplacement mémoire (alloué sur le tas ou la pile).Cela correspond à out
et ref
modificateurs en C#.Notez que vous ne pouvez pas créer de variable locale de ce type.
L'opérateur est un moyen de créer une valeur (un pointeur) qui peut être passée en argument à une fonction/méthode attendant un byref
taper.
Fonctions d'appel l'exemple avec byref
fonctionne parce que vous transmettez à la méthode une référence à une variable mutable locale.Via la référence, la méthode peut modifier la valeur stockée dans cette variable.
Ce qui suit ne fonctionne pas :
let a = 10 // Note: You don't even need 'mutable' here
bar.Increment(ref a)
La raison est que vous créez une nouvelle instance de Ref<int>
et vous copiez la valeur de a
dans cette instance.Le Increment
La méthode modifie ensuite la valeur stockée sur le tas dans le cas de Ref<int>
, mais vous n'avez plus de référence à cet objet.
let a = ref 10
bar.Increment(a)
Cela fonctionne, parce que a
est une valeur de type Ref<int>
et vous transmettez un pointeur vers l'instance allouée au tas à Increment
puis obtenez la valeur de la cellule de référence allouée au tas en utilisant !a
.
(Vous pouvez utiliser les valeurs créées à l'aide de ref
comme arguments pour byref
car le compilateur gère ce cas spécialement - il prendra automatiquement la référence du Value
champ car c'est un scénario utile...).