F #: laissez mutable vs. ref

Premièrement, je reconnais la possibilité que cette question puisse être un double; faites le moi savoir.

Je suis curieux de savoir quelle est la “meilleure pratique” générale pour les situations où la mutabilité est souhaitée. F # semble offrir deux possibilités pour cela: la liaison let mutable , qui semble fonctionner comme des variables dans la plupart des langages, et la cellule de référence (créée avec la fonction ref ) qui nécessite un déréférencement explicite à utiliser.

Il y a quelques cas où l’un est “forcé” dans l’un ou l’autre: .NET interop a tendance à utiliser mutable avec <- , et dans les calculs de workflow, il faut utiliser ref avec := . Donc, ces cas sont assez clairs, mais je suis curieux de savoir quoi faire lorsque je crée mes propres variables mutables en dehors de ces scénarios. Quel avantage un style a-t-il sur l’autre? (Peut-être qu’un aperçu supplémentaire de la mise en œuvre serait utile.)

Merci! (Et désolé pour “surutilisation” des guillemets.)

    Je ne peux que soutenir ce que gradbot a dit – quand j’ai besoin de mutation, je préfère let mutable .

    En ce qui concerne la mise en œuvre et les différences entre les deux, les cellules ref sont essentiellement implémentées par un enregistrement très simple contenant un champ d’enregistrement mutable. Vous pouvez les écrire facilement vous-même:

     type ref< 'T> = // ' { mutable value : 'T } // ' // the ref function, ! and := operators look like this: let (!) (a:ref<_>) = a.value let (:=) (a:ref<_>) v = a.value < - v let ref v = { value = v } 

    Une différence notable entre les deux approches est que let mutable stocke la valeur mutable sur la stack (en tant que variable mutable en C #) tandis que ref stocke la valeur mutable dans un champ d'un enregistrement alloué au tas. Cela peut avoir un impact sur la performance, mais je n'ai pas de chiffres ...

    Grâce à cela, les valeurs mutables qui utilisent ref peuvent être aliasées - ce qui signifie que vous pouvez créer deux valeurs faisant référence à la même valeur mutable:

     let a = ref 5 // allocates a new record on the heap let b = a // b references the same record b := 10 // modifies the value of 'a' as well! let mutable a = 5 // mutable value on the stack let mutable b = a // new mutable value initialized to current value of 'a' b < - 10 // modifies the value of 'b' only! 

    Question connexe: “Vous avez mentionné que les valeurs mutables locales ne peuvent pas être capturées par une fermeture, vous devez donc utiliser la référence à la place. La raison en est que les valeurs mutables capturées dans la fermeture doivent être allouées sur le tas le tas). ” à partir de F # ref-mutable vars vs champs d’object

    Je pense let mutable est préférable aux cellules de référence. Personnellement, je n’utilise que des cellules de référence lorsqu’elles sont requirejses.

    La plupart du code que j’écris n’utilise pas de variables mutables grâce aux appels de récursivité et de queue. Si j’ai un groupe de données mutables, j’utilise un enregistrement. Pour les objects que j’utilise, let mutable pour créer des variables privées mutables. Je n’utilise que des cellules de référence pour les fermetures, généralement les événements.

    Comme décrit dans cet article de MSDN Blog dans la section Utilisation simplifiée des valeurs mutables , vous n’avez plus besoin de cellules ref pour les lambdas. Donc, en général, vous n’en avez plus besoin du tout.

    Cet article de Brian pourrait fournir une réponse.

    Les mutables sont faciles à utiliser et efficaces (sans emballage), mais ne peuvent pas être capturés dans les Lambda. Les cellules de référence peuvent être capturées, mais sont verbeuses et moins efficaces (? Pas sûr).

    Vous voudrez peut-être jeter un coup d’œil à la section Mutable Data dans le wikibook.

    Pour plus de commodité, voici quelques citations pertinentes:

    Le mot-clé mutable est fréquemment utilisé avec les types d’enregistrement pour créer des enregistrements modifiables.

    Les variables mutables sont quelque peu limitées: les mutables sont inaccessibles en dehors de la scope de la fonction où elles sont définies. Plus précisément, cela signifie qu’il n’est pas possible de référencer un mutable dans une sous-fonction d’une autre fonction.

    Les cellules Ref contournent certaines des limitations des mutables. En fait, les cellules ref sont des types de données très simples qui enveloppent un champ mutable dans un type d’enregistrement.

    Comme les cellules ref sont allouées sur le tas, elles peuvent être partagées entre plusieurs fonctions