2012-06-22 15 views
8

Sé que las variables en F # son inmutables por defecto. Pero, por ejemplo, en C# interactivo:inmutable en F #

> let x = 4;; 

val x : int = 4 

> let x = 5;; 

val x : int = 5 

> x;; 
val it : int = 5 
> 

Así, asigno a 4 x, entonces x 5 a y está cambiando. ¿Es correcto? ¿Debería dar algún error o advertencia? ¿O simplemente no entiendo cómo funciona?

+1

Posible duplicado de http://stackoverflow.com/questions/2844047/what-is-the-let-keyword-in-functional-languages -like-f-and-ocaml-for.Las respuestas allí explican la distinción entre enlace variable y asignación variable. – Heatsink

+1

@Alex: Puede encontrar las respuestas a [esta pregunta] útiles (http://stackoverflow.com/questions/2478079/f-shadowing-and-nested-function). – Daniel

+0

La pregunta es similar pero no es un duplicado. –

Respuesta

14

Cuando se escribe let x = 3, que son vinculantes para el identificador x al valor 3. Si lo hace por segunda vez en el mismo ámbito, está declarando un nuevo identificador que oculta el anterior, ya que tiene el mismo nombre.

La mutación de un valor en F # se realiza a través del operador de actualización destructiva, <-. Esto se producirá un error para los valores inmutables, es decir .:

> let x = 3;; 

val x : int = 3 

> x <- 5;; 

    x <- 5;; 
    ^^^^^^ 

stdin(2,1): error FS0027: This value is not mutable 

Declarar una variable mutable, añadir mutable después let:

let mutable x = 5;; 

val mutable x : int = 5 

> x <- 6;; 
val it : unit =() 
> x;; 
val it : int = 6 

pero ¿cuál es la diferencia entre los dos, usted puede pedir? Un ejemplo puede ser suficiente:

let i = 0; 
while i < 10 do 
    let i = i + 1 
    () 

A pesar de las apariencias, este es un ciclo infinito. El i declarado dentro del ciclo es un i diferente que oculta el exterior. El exterior es inmutable, por lo que siempre mantiene su valor 0 y el bucle nunca termina. La forma correcta de escribir esto es con una variable mutable:

let mutable i = 0; 
while i < 10 do 
    i <- i + 1 
    () 
5

x no ha cambiado, simplemente está oculto por la próxima declaración. Por ejemplo:

> let x = 4;; 
val x : int = 4 
> let x = "abc";; 
val x : string = "abc" 
> 
+0

¿Cuál es la diferencia entre oculto e inmutable? ¿Significa que todavía puedo obtener el valor anterior de x? – Alexan

+1

@Alex vea mi respuesta para obtener una explicación de la diferencia. – Asik

4

no estamos asignando a 5 x, está definiendo una nueva variable.

El siguiente ejemplo muestra que hay dos variables distintas. (También demuestra que se puede "acceso" los viejos X si se encuentra en un cierre, que se utiliza por otra función):

let x = 5;; 
let f y = y+x;; 
f 10;; 
let x = 0;; 
f 10;; 

produce

> 
val x : int = 5 

> 
val f : int -> int 
> val it : int = 15 
> 
val x : int = 0 

> val it : int = 15 

como se ve, ambas llamadas a f use la primera variable x. La definición let x = 0;; define una nueva variable x, pero no redefine f.

3

Aquí hay un ejemplo que ilustra identificador mínimo "sombra" (escondite es decir) en Fa #:

let x = 0 
do //introduce a new lexical scope 
    let x = 1 //"shadow" (i.e. hide) the previous definition of x 
    printfn "%i" x //prints 1 
//return to outer lexical scope 
printfn "%i" x //prints 0, proving that our outer definition of x was not mutated by our inner definition of x 

Su ejemplo es en realidad un poco más compleja, porque se está trabajando en el F # Interactivo (FSI). FSI emite dinámicamente el código que se ve algo como lo siguiente en su ejemplo:

module FSI_0001 = 
    let x = 4;; 

open FSI_0001 //x = 4 is now available in the top level scope 
module FSI_0002 = 
    let x = 5;; 

open FSI_0002 //x = 5 is now available in the top level scope, hiding x = 4 
module FSI_0003 = 
    let it = x;; 

open FSI_0003 
//... subsequent interactions