Primero, reconozco la posibilidad de que esta pregunta sea un duplicado; sólo házmelo saber.
Tengo curiosidad por saber cuál es la "mejor práctica" general para aquellas situaciones en las que se desea la mutabilidad. F # parece ofrecer dos facilidades para esto: el let mutable
enlace, que parece funcionar como variables en "la mayoría" de los lenguajes, y la celda de referencia (creada con la ref
función) que requiere una desreferenciación explícita para su uso.
Hay un par de casos en los que uno es "forzado" en uno u otro: la interoperabilidad de .NET tiende a usarse mutable con <-
, y en los cálculos de flujo de trabajo uno debe usar ref
con :=
. Entonces, esos casos son bastante claros, pero tengo curiosidad por saber qué hacer al crear mis propias variables mutables fuera de esos escenarios. ¿Qué ventaja tiene un estilo sobre el otro? (Quizás sería útil conocer mejor la implementación).
¡Gracias!
Respuestas:
Solo puedo apoyar lo que dijo Gradbot : cuando necesito una mutación, lo prefiero
let mutable
.Con respecto a la implementación y las diferencias entre las dos
ref
celdas, esencialmente se implementan mediante un registro muy simple que contiene un campo de registro mutable. Podrías escribirlos fácilmente tú mismo: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 }
Una diferencia notable entre los dos enfoques es que
let mutable
almacena el valor mutable en la pila (como una variable mutable en C #) mientrasref
almacena el valor mutable en un campo de un registro asignado al montón. Esto puede tener algún impacto en el rendimiento, pero no tengo números ...Gracias a esto, los valores mutables que se usan
ref
pueden tener un alias, lo que significa que puede crear dos valores que hagan referencia al mismo valor 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!
fuente
Pregunta relacionada: "Mencionaste que los valores mutables locales no pueden ser capturados por un cierre, por lo que debes usar ref en su lugar. La razón de esto es que los valores mutables capturados en el cierre deben asignarse en el montón (porque el cierre se asigna en el montón) ". de F # ref-mutable vars vs campos de objeto
Creo que
let mutable
se prefiere a las celdas de referencia. Personalmente, solo uso celdas de referencia cuando son necesarias.La mayoría del código que escribo no usa variables mutables gracias a la recursividad y las llamadas de cola. Si tengo un grupo de datos mutables, uso un registro. Para los objetos que uso
let mutable
para hacer variables privadas mutables. Realmente solo uso celdas de referencia para cierres, generalmente eventos.fuente
Como se describe en este artículo del blog de MSDN en la sección Uso simplificado de valores mutables , ya no necesita celdas de referencia para lambdas. Entonces, en general, ya no los necesita en absoluto.
fuente
Este artículo de Brian podría proporcionar una respuesta.
Los mutables son fáciles de usar y eficientes (sin envoltura), pero no se pueden capturar en lambdas. Las celdas de referencia se pueden capturar, pero son detalladas y menos eficientes (? - no estoy seguro de esto).
fuente
Es posible que desee echar un vistazo a la sección Datos mutables en el wikilibro.
Para mayor comodidad, aquí hay algunas citas relevantes:
fuente