2012-06-22 23 views
8

So che le variabili in F # sono immutabili per impostazione predefinita. Ma, per esempio in F # interattivo:immutabile in F #

> let x = 4;; 

val x : int = 4 

> let x = 5;; 

val x : int = 5 

> x;; 
val it : int = 5 
> 

Così, ho assegnare 4 x, poi da 5 a x e sta cambiando. È corretto? Dovrebbe dare qualche errore o avvertimento? O semplicemente non capisco come funziona?

+1

Eventuali duplicati di http://stackoverflow.com/questions/2844047/what-is-the-let-keyword-in-functional-languages -come-f-e-ocaml-per.Le risposte là spiegano la distinzione tra associazione variabile e assegnazione variabile. – Heatsink

+1

@Alex: è possibile trovare le risposte a [questa domanda] (http://stackoverflow.com/questions/2478079/f-shadowing-and-nested-function) utili. – Daniel

+0

La domanda è simile ma non è un duplicato. –

risposta

14

Quando si scrive let x = 3, si sono vincolanti l'identificatore x al valore 3. Se lo fai una seconda volta nello stesso ambito, stai dichiarando un nuovo identificatore che nasconde il precedente poiché ha lo stesso nome.

La modifica di un valore in F # viene effettuata tramite l'operatore di aggiornamento distruttivo, <-. Questo fallirà per i valori immutabili, cioè .:

> let x = 3;; 

val x : int = 3 

> x <- 5;; 

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

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

dichiarare una variabile mutabile, aggiungere mutable dopo let:

let mutable x = 5;; 

val mutable x : int = 5 

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

Ma qual è la differenza tra i due, si potrebbe chiedere? Un esempio potrebbe essere sufficiente:

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

Nonostante le apparenze, questo è un ciclo infinito. Il i dichiarato all'interno del ciclo è diverso i che nasconde quello esterno. Quello esterno è immutabile, quindi mantiene sempre il suo valore 0 e il ciclo non finisce mai. Il modo corretto di scrivere questo è con una variabile mutabile:

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

x non viene modificato, è solo nascosto dalla prossima dichiarazione. Per esempio:

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

Qual è la differenza tra nascosto e immutabile? Significa che posso ancora ottenere il valore precedente di x? – Alexan

+1

@Alex vedere la mia risposta per una spiegazione della differenza. – Asik

4

Non stai assegnando 5-x, si sta definendo una nuova variabile.

L'esempio seguente mostra che esistono due variabili distinte. (mostra anche che è possibile "accesso" ai vecchi x se si trova in una chiusura, utilizzato da un'altra funzione):

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 

, come si vede, le chiamate per f utilizzare la prima variabile x. La definizione let x = 0;; definisce una nuova variabile x, ma non ridefinisce f.

3

Ecco un minimo esempio che illustra identificatore "shadowing" (cioè nascosto) in F #:

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 

Il vostro esempio è in realtà un po 'più complesso, perché si sta lavorando in F # Interactive (FSI). FSI emette dinamicamente il codice che sembra qualcosa di simile al seguente nel tuo esempio:

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