2012-06-22 34 views
8

Tôi biết rằng các biến trong F # là không thay đổi theo mặc định. Nhưng, ví dụ như trong F # tương tác:không thay đổi trong F #

> let x = 4;; 

val x : int = 4 

> let x = 5;; 

val x : int = 5 

> x;; 
val it : int = 5 
> 

Vì vậy, tôi gán 4 đến x, sau đó 5 đến x và nó đang thay đổi. Nó có đúng không? Nó có nên đưa ra một số lỗi hoặc cảnh báo? Hoặc tôi chỉ không hiểu nó hoạt động như thế nào?

+1

Có thể trùng lặp của http://stackoverflow.com/questions/2844047/what-is-the-key-inword-in-functional-languages -like-f-và-ocaml-for.Các câu trả lời có giải thích sự khác biệt giữa biến ràng buộc và chuyển nhượng biến. – Heatsink

+1

@ Alex: Bạn có thể tìm thấy câu trả lời cho [câu hỏi này] (http://stackoverflow.com/questions/2478079/f-shadowing-and-nested-function) hữu ích. – Daniel

+0

Câu hỏi tương tự nhưng không trùng lặp. –

Trả lời

14

Khi bạn viết let x = 3, bạn phải ràng buộc các định danh x với giá trị 3. Nếu bạn làm điều đó lần thứ hai trong cùng một phạm vi, bạn đang khai báo một mã định danh mới ẩn phần trước đó vì nó có cùng tên.

Việc tắt một giá trị trong F # được thực hiện thông qua toán tử cập nhật phá hủy, <-. Điều này sẽ không cho các giá trị bất biến, tức là .:

> let x = 3;; 

val x : int = 3 

> x <- 5;; 

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

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

Để khai báo một biến có thể thay đổi, thêm mutable sau let:

let mutable x = 5;; 

val mutable x : int = 5 

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

Nhưng những gì là sự khác biệt giữa hai, bạn có thể yêu cầu? Ví dụ có thể là đủ:

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

Mặc dù xuất hiện, đây là vòng lặp vô hạn. Các i tuyên bố bên trong vòng lặp là một i khác nhau mà ẩn bên ngoài. Cái bên ngoài là không thay đổi, vì vậy nó luôn giữ giá trị 0 và vòng lặp không bao giờ kết thúc. Các cách chính xác để viết những dòng này là với một biến có thể thay đổi:

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

x không thay đổi, nó chỉ bị ẩn bởi tuyên bố tiếp theo. Ví dụ:

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

Sự khác biệt giữa ẩn và bất biến là gì? Liệu nó có nghĩa là tôi vẫn có thể nhận được giá trị trước đó của x? – Alexan

+1

@Alex xem câu trả lời của tôi cho một lời giải thích về sự khác biệt. – Asik

4

Bạn không gán 5-x, bạn đang xác định một biến mới.

Ví dụ sau cho thấy có hai biến riêng biệt. (Nó cũng cho thấy rằng bạn có thể "truy cập" x cũ nếu nó nằm trong một đóng cửa, được sử dụng bởi chức năng khác):

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

mang

> 
val x : int = 5 

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

> val it : int = 15 

như bạn thấy, cả hai cuộc gọi đến f sử dụng biến đầu tiên x. Định nghĩa let x = 0;; xác định biến mới x nhưng không xác định lại f.

3

Dưới đây là một ví dụ minh họa tối thiểu nhận dạng "shadowing" (ví dụ: ẩn) trong 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 

dụ của bạn là thực sự phức tạp hơn một chút, bởi vì bạn đang làm việc trong F # Interactive (FSI). FSI tự động phát ra mã trông giống như sau trong ví dụ của bạn:

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 
Các vấn đề liên quan