2013-05-12 7 views
7

# 3.0 एफ क्रिस स्मिथ के प्रोग्रामिंग से एक उदाहरण का उपयोग करना:Fsharp इंटरएक्टिव क्यों बंद करने से परिवर्तनीय चर को पकड़ने की अनुमति देता है?

let invalidUseOfMutable() = 
    let mutable x = 0 
    let incrementX() = x <- x + 1 
    incrementX() 
    x;; 

यह अपेक्षा के अनुरूप विफल रहता है:

त्रुटि FS0407: परिवर्तनशील चर 'एक्स' गलत तरीके से प्रयोग किया जाता है। परिवर्तनीय चर को बंद करके पकड़ा नहीं जा सकता है।

अब कट और FSharp इंटरएक्टिव में समारोह के शरीर पेस्ट:

let mutable x = 0 
let incrementX() = x <- x + 1 
incrementX() 
x;; 

और यह काम करता है!

वैल यह: पूर्णांक = 1

क्यों?

+0

नमस्ते, जब आप केवल शरीर कोड चलाते हैं तो यह बंद नहीं होता है। उपयोग: x = ref 0; incrementX() = x: =! x + 1; क्लोजर देखें: http: //msdn.microsoft.com/en-us/library/dd233186.aspx – kwingho

+0

ध्यान दें कि कंपाइलर भी शरीर के लिए ऑब्जेक्ट नहीं करता है अपने आप पर कार्य करें। –

उत्तर

8

संक्षिप्त उत्तर: यह fsi की वजह से नहीं है, ऐसा इसलिए है क्योंकि उत्परिवर्तनीय वैश्विक है।

लांग जवाब:

एक सामान्य (गैर परिवर्तनशील) पर कब्जा के लिए, कार्यान्वयन के लिहाज से कब्जा कर लिया मूल्य, समारोह वस्तु में बनाई जाए ताकि यदि आप इस समारोह लौट सकते हैं और दायरे के बाहर इसका इस्तेमाल जिसमें यह परिभाषित किया गया है, सब कुछ ठीक काम करता है।

let pureAddOne() = 
    let x = 1 
    let f y = x + y // the value 1 is copied into the function object 
    f 

let g = pureAddOne() 
g 3 // x is now out of scope, but its value has been copied and can be used 

दूसरी ओर, आदेश में एक परिवर्तनशील पर कब्जा करने में, कब्जा संदर्भ द्वारा किया जाना चाहिए, और आप इसे संशोधित करने में सक्षम नहीं होगा। लेकिन यह असंभव है, क्योंकि पहले उल्लिखित मामले में जहां बंद कर दिया गया है और इसकी परिभाषा के दायरे के बाहर उपयोग किया जाता है, म्यूटेबल भी दायरे से बाहर है और संभावित रूप से हटा दिया गया है। प्रारंभिक सीमा का यही कारण है।

let mutableAddOne() = 
    let mutable x = 1 
    let f y = x <- x + y // x would be referenced, not copied 
    f 

let g = mutableAddOne() 
g 3 // x is now out of scope, so the reference is invalid! 
     // mutableAddOne doesn't compile, because if it did, then this would fail. 

हालांकि, अगर परिवर्तनशील वैश्विक है, तो ऐसी कोई गुंजाइश मुद्दा है, और संकलक यह स्वीकार करता है। यह सिर्फ fsi नहीं है; यदि आप fsc साथ निम्नलिखित कार्यक्रम संकलित करने के लिए प्रयास करते हैं, यह काम करता है:

module Working 

let mutable x = 1 // x is global, so it never goes out of scope 

let mutableAddOne() = 
    let f y = x <- x + y // referencing a global. No problem! 
    f 

let g = mutableAddOne() 
g 3 // works as expected! 

अंत में, के रूप में kwingho कहा, यदि आप एक बंद है कि एक स्थानीय परिवर्तनशील मूल्य कब्जा करना चाहते हैं, एक ref का उपयोग करें। वे ढेर-आवंटित होते हैं (स्टैक-आवंटित स्थानीय उत्परिवर्तनीय के विपरीत) ताकि जब तक बंद करने का संदर्भ हो, तब तक इसे अस्वीकार नहीं किया जाएगा।

संबंधित मुद्दे