2010-02-08 3 views

Répondre

12

La question est, comment voulez-vous modifier la valeur d'un élément mutable de cas de discrimination syndicale? Pour ref types, cela est assez facile, parce que ref est une cellule de référence (un record en fait) qui contient la valeur mutable:

match tval with 
| B(str, refNum) -> refNum := 4 

On extrait la cellule de référence et lui attribuer un nouveau symbole (ou une nouvelle variable) refNum. Ensuite, nous modifions la valeur à l'intérieur de la cellule ref, qui modifie également tval, car les deux références à la cellule (à partir de l'union discriminée et de la variable refNum) sont aliasées. D'autre part, lorsque vous écrivez let mutable n = 0, vous créez une variable, qui peut être directement muté, mais il n'y a pas de cellule contenant la valeur mutable - la variable n est directement modifiable. Cela montre la différence:

let mutable a = 10 
let mutable b = a 
b <- 5 // a = 10, b = 5 

let a = ref 10 
let b = a 
b := 5 // a = 5, b = 5 (because of aliasing!) 

Donc, pour répondre à votre question - il n'y a pas moyen de se référer directement à la valeur stockée dans le cas des syndicats discriminés. Vous pouvez uniquement l'extraire à l'aide de la correspondance de modèle, mais cela copie la valeur dans une nouvelle variable. Cela signifie qu'il n'y a aucun moyen de modifier la valeur mutable.

EDIT Pour démontrer les limites de mutable valeurs F #, voici un exemple - vous ne pouvez pas capturer mutable valeurs à l'intérieur d'une fermeture:

let foo() = 
    let mutable n = 0 
    (fun() -> n <- n + 1; n) // error FS0407 

Je pense que la raison est la même que les cas discriminés syndicaux (même si ce n'est pas aussi évident dans ce cas). Le compilateur doit copier la variable - il est stocké en tant que variable locale et en tant que champ dans la fermeture générée. Et lors de la copie, vous voulez modifier la même variable à partir de plusieurs références, donc sémantique d'alias est la seule chose raisonnable à faire ...

+0

En créant une variable typée comme une union discriminée comme un enregistrement, nous avons déjà des cellules mémoire, n'est-ce pas? Je suppose, en utilisant la correspondance de modèle que nous créons encore une autre liaison à la cellule de mémoire existante, ni de créer une nouvelle variable directement modifiable, n'est pas? D'un autre côté, vos arguments semblent raisonnables, mais Leroy tout en décrivant ZINC montre qu'une telle syntaxe est possible. – ssp

+0

J'ai vérifié ZINC et il utilise vraiment mutable dans les unions discriminées. Bien qu'il ne me soit pas clair s'il suit la sémantique _aliasing_ ou si vous pouvez changer la valeur seulement par le symbole lié dans la correspondance de modèle (si c'est le cas, cela me semble un peu incohérent) parce que la correspondance a déjà copié la valeur cas pour un symbole ...) –

+0

Pour autant que j'entende le code de ZINC, Leroy vient de lier un nom utilisé dans le modèle correspondant à l'étiquette du membre DU (et l'étiquette est juste index dans la table des offsets au membre DU). Ainsi, dans le cas où le compilateur F # crée une copie locale du membre DU, c'est vraiment impossible. Merci beaucoup! – ssp

5

Ref est un type (int ref = ref<int>). Mutable n'est pas un type, c'est un mot-clé qui vous permet de mettre à jour une valeur.

Exemple:

let (bla:ref<int>) = ref 0 //yup 
let (bla:mutable<int>) = 3 //no! 
+0

Votre exemple montre juste qu'il n'y a pas de type mutable. Oui, je suis d'accord: mutable est juste marquer au compilateur d'utiliser de la syntaxe du sucre. Je peux imaginer pourquoi cette marque ne peut pas être incluse dans l'environnement et donc nous ne pouvons pas utiliser des variables mutables avec des fermetures. À mon humble avis, en créant une union typée comme discriminée en tant qu'enregistrement, nous mangeons déjà des cellules de mémoire (f.e. ref n'est plus alors {mutable 'a val}). Alors pourquoi une union discriminée ne peut-elle pas être mutable? – ssp

Questions connexes