एफ #: पारस्परिक रूप से देखें


83

पहले, मैं इस संभावना को स्वीकार करता हूं कि यह प्रश्न एक डुप्लिकेट हो सकता है; बस मुझे पता है।

मुझे उत्सुकता है कि क्या सामान्य "सर्वश्रेष्ठ अभ्यास" उन स्थितियों के लिए है जब उत्परिवर्तन वांछित है। F # इसके लिए दो सुविधाएं प्रदान करता है: let mutableबाइंडिंग, जो "सबसे" भाषाओं में चर की तरह काम करता है, और संदर्भ सेल ( refफ़ंक्शन के साथ बनाया गया ) जिसे उपयोग करने के लिए स्पष्ट dereferencing की आवश्यकता होती है।

ऐसे मामलों की एक जोड़ी जहां एक के बाद एक या अन्य में "मजबूर" है: .NET इंटरॉप साथ परिवर्तनशील उपयोग करने के लिए जाता है <-, और कार्यप्रवाह संगणना में एक का उपयोग करना चाहिए refके साथ :=। तो उन मामलों में बहुत स्पष्ट हैं, लेकिन मैं उत्सुक हूं कि उन परिदृश्यों के बाहर अपने स्वयं के परिवर्तनशील चर बनाते समय क्या करना चाहिए। एक शैली का दूसरे पर क्या लाभ है? (शायद कार्यान्वयन में आगे की अंतर्दृष्टि मदद करेगी।)

धन्यवाद!



4
ध्यान दें कि एफ # संस्करण 4 में, उत्परिवर्तनीय का उपयोग किया जा सकता है जहां आपको रेफ की आवश्यकता होती है। blogs.msdn.com/b/fsharpteam/archive/2014/11/12/…
जेम्स मूर

जवाबों:


134

मैं केवल उसी चीज का समर्थन कर सकता हूं जो ग्रेडबोट ने कहा था - जब मुझे म्यूटेशन की आवश्यकता होती है, तो मैं पसंद करता हूं let mutable

कार्यान्वयन और दोनों के बीच अंतर के संबंध में - refकोशिकाओं को अनिवार्य रूप से एक बहुत ही सरल रिकॉर्ड द्वारा कार्यान्वित किया जाता है जिसमें एक परस्पर रिकॉर्ड क्षेत्र होता है। आप उन्हें स्वयं आसानी से लिख सकते हैं:

type ref<'T> =  // '
  { mutable value : 'T } // '

// the ref function, ! and := operators look like this:
let (!) (a:ref<_>) = a.value
let (:=) (a:ref<_>) v = a.value <- v
let ref v = { value = v }

दो दृष्टिकोणों के बीच एक उल्लेखनीय अंतर यह है कि let mutableढेर पर उत्परिवर्तनीय मूल्य (सी # में एक उत्परिवर्तनीय चर के रूप में) refसंग्रहीत करता है, जबकि एक ढेर-आवंटित रिकॉर्ड के क्षेत्र में परस्पर मूल्य को संग्रहीत करता है। इससे प्रदर्शन पर कुछ प्रभाव पड़ सकता है, लेकिन मेरे पास कोई संख्या नहीं है ...

इसके लिए धन्यवाद, परस्पर उपयोग करने वाले मूल्यों को refअलग किया जा सकता है - जिसका अर्थ है कि आप दो मान बना सकते हैं जो समान परिवर्तनशील मूल्य का संदर्भ देते हैं:

let a = ref 5  // allocates a new record on the heap
let b = a      // b references the same record
b := 10        // modifies the value of 'a' as well!

let mutable a = 5 // mutable value on the stack
let mutable b = a // new mutable value initialized to current value of 'a'
b <- 10           // modifies the value of 'b' only!

2
बस एक अनुस्मारक: स्टैक पर या ढेर पर होना एक कार्यान्वयन विवरण है और सवाल के लिए बिल्कुल प्रासंगिक नहीं है (लेकिन फिर भी उत्कृष्ट उत्तर)
ब्रूनो ब्रेंट

5
मेरा तर्क है कि यह जानना कि क्या कुछ ढेर आवंटन और संग्रह के ओवरहेड को उकसाता है या नहीं जब सबसे अच्छा अभ्यास है, तो यह तय करना बेहद प्रासंगिक है।
जैकमॉट 19

@jackmott ने इस लेख को एरिक लिपर्ट द्वारा द स्टैक इज एन इंप्लीमेंटेशन डिटेल
jaromey

5
@jaromey हाँ, मैं समझता हूँ कि मैं बुनियादी तौर पर उस बिंदु पर पूरी तरह से असहमत हूँ। जब 'सबसे अच्छा अभ्यास' होता है, तो आप प्रदर्शन के विचारों को एक तरफ नहीं छोड़ सकते। अक्सर यह दावा किया जाता है कि एक हजार कार्यान्वयन विवरण से मृत्यु के कारण प्रदर्शन अभी तक बहुत अधिक सॉफ्टवेयर धीमा नहीं है।
जैकमॉट

18

संबंधित प्रश्न: "आपने उल्लेख किया है कि स्थानीय परिवर्तनशील मूल्यों को एक बंद द्वारा कब्जा नहीं किया जा सकता है, इसलिए आपको इसके बजाय रेफ का उपयोग करने की आवश्यकता है। इसका कारण यह है कि क्लोजर में कैप्चर किए गए उत्परिवर्तनीय मानों को ढेर पर आवंटित किया जाना चाहिए (क्योंकि क्लोजर आवंटित किया गया है) ढेर) से एफ # रेफरी-परिवर्तनशील वार्स बनाम ऑब्जेक्ट फ़ील्ड

मुझे लगता let mutableहै कि संदर्भ कोशिकाओं पर पसंद किया जाता है। मैं व्यक्तिगत रूप से केवल संदर्भ कोशिकाओं का उपयोग करता हूं जब उनकी आवश्यकता होती है।

अधिकांश कोड जो मैं लिखता हूं वह पुनरावृत्ति और पूंछ कॉल के लिए उत्परिवर्तनीय चर का उपयोग नहीं करता है। यदि मेरे पास उत्परिवर्तनीय डेटा का एक समूह है, तो मैं एक रिकॉर्ड का उपयोग करता हूं। उन वस्तुओं के लिए जिनका मैं let mutableनिजी परिवर्तनशील चर बनाने के लिए उपयोग करता हूं । मैं केवल क्लोजर के लिए संदर्भ कोशिकाओं का उपयोग करता हूं, आम तौर पर घटनाओं के लिए।


9

खंड में इस MSDN ब्लॉग लेख में वर्णित के रूप में , परिवर्तनशील मूल्यों का सरलीकृत उपयोग , अब आपको लैम्ब्डा के लिए रेफरी कोशिकाओं की आवश्यकता नहीं है। तो सामान्य तौर पर अब आपको उनकी बिल्कुल भी आवश्यकता नहीं है।


4

ब्रायन का यह लेख एक उत्तर प्रदान कर सकता है।

म्यूटैबल्स का उपयोग करना आसान है और कुशल (रैपिंग नहीं), लेकिन लैम्ब्डा में कब्जा नहीं किया जा सकता है। रेफरी कोशिकाओं पर कब्जा किया जा सकता है, लेकिन क्रिया और कम कुशल हैं (-? यह सुनिश्चित नहीं है)।


"(...) और कम कुशल" - शायद, एक आवरण प्रकार अधिक स्मृति लेता है।
JMCF125

2
यह बदल गया है, क्योंकि एफ # 4.0 उत्परिवर्तनीय को ज्यादातर मामलों में पकड़ा जा सकता है और रेफ की आवश्यकता अब बहुत कम है।
हाबिल १

3

आप वाइकबुक में Mutable Data सेक्शन पर एक नज़र डालना चाहते हैं।

सुविधा के लिए, यहां कुछ प्रासंगिक उद्धरण दिए गए हैं:

म्यूटेबल कीवर्ड का उपयोग अक्सर म्यूट रिकॉर्ड बनाने के लिए रिकॉर्ड प्रकारों के साथ किया जाता है

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

रेफ कोशिकाओं को उत्परिवर्तनों की कुछ सीमाओं के आसपास मिलता है। वास्तव में, रेफ सेल बहुत सरल डेटा प्रकार होते हैं जो एक रिकॉर्ड प्रकार में एक उत्परिवर्तनीय क्षेत्र को लपेटते हैं।

चूंकि रेफ कोशिकाओं को ढेर पर आवंटित किया जाता है, उन्हें कई कार्यों में साझा किया जा सकता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.