2012-06-22 23 views
8

में अपरिवर्तनीय मुझे पता है कि एफ # में चर डिफ़ॉल्ट रूप से अपरिवर्तनीय हैं। लेकिन, एफ # इंटरैक्टिव में उदाहरण के लिए:एफ #

> let x = 4;; 

val x : int = 4 

> let x = 5;; 

val x : int = 5 

> x;; 
val it : int = 5 
> 

तो, मैं 4 x करने के लिए प्रदान करते हैं तो एक्स के लिए 5 और यह बदल रहा है। क्या यह सही है? क्या यह कुछ त्रुटि या चेतावनी देना चाहिए? या मैं समझ में नहीं आता कि यह कैसे काम करता है?

+1

संभावित डुप्लिकेट http://stackoverflow.com/questions/2844047/what-is-the-let-keyword-in-functional-languages: FSI गतिशील कोड है कि आपके उदाहरण में निम्नलिखित की तरह कुछ लग रहा है का उत्सर्जन करता है -like-एफ-एंड-ओकंपल-के लिए।उत्तर वहां परिवर्तनीय बाध्यकारी और परिवर्तनीय असाइनमेंट के बीच भेद की व्याख्या करते हैं। – Heatsink

+1

@Alex: आपको [इस प्रश्न] के उत्तर मिल सकते हैं (http://stackoverflow.com/questions/2478079/f-shadowing-and-nested-function) सहायक। – Daniel

+0

प्रश्न समान है लेकिन यह एक डुप्लिकेट नहीं है। –

उत्तर

14

जब आप let x = 3 लिखते हैं, आप मूल्य 3 को पहचानकर्ता x बाध्यकारी हैं। यदि आप एक ही समय में दूसरी बार ऐसा करते हैं, तो आप एक नया पहचानकर्ता घोषित कर रहे हैं जो पिछले एक को छुपाता है क्योंकि उसका नाम समान है।

एफ # में एक मान को म्यूट करना विनाशकारी अद्यतन ऑपरेटर, <- के माध्यम से किया जाता है। यह अपरिवर्तनीय मूल्यों के लिए असफल हो जायेगी, यानी .:

> let x = 3;; 

val x : int = 3 

> x <- 5;; 

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

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

एक परिवर्तनशील चर घोषित करने के लिए, mutable जोड़ने let के बाद:

let mutable x = 5;; 

val mutable x : int = 5 

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

लेकिन क्या दोनों के बीच अंतर, आप पूछ सकते हैं है? एक उदाहरण पर्याप्त हो सकता है:

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

उपस्थिति के बावजूद, यह एक अनंत लूप है। लूप के अंदर घोषित i एक अलग i है जो बाहरी को छुपाता है। बाहरी एक अपरिवर्तनीय है, इसलिए यह हमेशा अपना मान 0 रखता है और लूप कभी समाप्त नहीं होता है। इस लिखने के लिए सही तरीका एक परिवर्तनशील चर के साथ है:

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

x नहीं बदला गया है, यह सिर्फ अगली घोषणा द्वारा छुपा हुआ है। उदाहरण के लिए:

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

छुपा और अपरिवर्तनीय के बीच क्या अंतर है? क्या इसका मतलब यह है कि मुझे अभी भी एक्स का पिछला मान मिल सकता है? – Alexan

+1

@ एलेक्स अंतर के स्पष्टीकरण के लिए मेरा उत्तर देखें। – Asik

4

आप x को 5 बताए नहीं कर रहे हैं, आप एक नया चर को परिभाषित कर रहे हैं।

निम्नलिखित उदाहरण से पता चलता है कि दो अलग-अलग चर हैं। (यह भी पता चलता है कि आप "पहुँच" पुराने एक्स अगर यह एक बंद में है, एक और समारोह के द्वारा प्रयोग किया जा सकता है):

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

पैदावार

> 
val x : int = 5 

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

> val it : int = 15 

जैसा कि आप देख, च के दोनों कॉल पहले चर x का उपयोग करें। परिभाषा let x = 0;; एक नया चर x परिभाषित करता है, लेकिन f को फिर से परिभाषित नहीं करता है।

3

यहाँ एक न्यूनतम उदाहरण illustrating पहचानकर्ता एफ # में "पीछा" (यानी छुपा) है:

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 

आपका उदाहरण वास्तव में, थोड़े और जटिल है, क्योंकि आप एफ # इंटरएक्टिव (FSI) में काम कर रहे हैं। की

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