मैंने सुना एफ # अचल स्थिति के लिए देशी समर्थन लेकिन इसके बारे में क्या है कि सी # में दोहराया नहीं जा सकता है? आप एक एफ # अपरिवर्तनीय डेटा से क्या प्राप्त करते हैं जिसे आपको सी # अपरिवर्तनीय डेटा से नहीं मिलता है?एफ # ओवर सी # की अंतर्निहित अपरिवर्तनीयता के क्या फायदे हैं?
इसके अलावा एफ # में, परिवर्तनशील डेटा बनाने के लिए कोई रास्ता नहीं है? सब कुछ अपरिवर्तनीय है?
आप किसी अनुप्रयोग में दोनों सी # और एफ # का उपयोग करते हैं, तो आप सी # में अपरिवर्तनीय एफ # डेटा को बदल सकते हैं? या क्या आपको केवल नए सी # प्रकार बनाना है जो अपरिवर्तनीय F # डेटा का उपयोग करते हैं और उन संदर्भों को प्रतिस्थापित करते हैं जो उन डेटा को इंगित करते हैं?
उत्तर
तरह से एफ # काम करता है यह आसान अपरिवर्तनीय डेटा के साथ काम करने के लिए, लेकिन कुछ खास नहीं है कि सी # में इस संबंध में नहीं किया जा सकता है बनाता है। हालांकि यह साफ वाक्यविन्यास प्रदान नहीं कर सकता है।
एफ #
mutable
कीवर्ड के साथ परिवर्तनशील डेटा का समर्थन करता है। एफ # एक शुद्ध कार्यात्मक भाषा नहीं है। यह लूपों के साथ-साथ कार्यात्मक संरचनाओं जैसे अनिवार्य संरचनाओं का समर्थन करता है।नंबर अपरिवर्तनीय प्रकार वास्तव में अपरिवर्तनीय हैं। .NET प्रकार प्रणाली दोनों भाषाओं में साझा की जाती है। आप सी # से अपरिवर्तनीय डेटा नहीं बदल सकते हैं (निश्चित रूप से प्रतिबिंब और स्मृति हैक की कमी)।
अपरिवर्तनीयता के संबंध में एफ # और सी # के बीच सबसे बड़ा अंतर यह है कि एफ # डिफ़ॉल्ट रूप से अपरिवर्तनीय है। सी # में सभी अपरिवर्तनीय संरचनाओं और संग्रहों को दोहराना संभव है लेकिन अतिरिक्त कार्य के लॉट लेते हैं। एफ # में आप इसे मुफ्त में प्राप्त करते हैं।
एफ # एक संकर भाषा है और रूपों की एक जोड़ी में अस्थिरता का समर्थन करता है। परिवर्तनशील कीवर्ड
let value1 = 42; // immutable
let mutable value2 = value1; // mutable
value2 <- 13;
प्रतिबिंब चाल वर्जित में सरल, एक बार डेटा एफ # में बन जाता है यह भाषा से आप उपभोग पर ध्यान दिए बिना अपरिवर्तनीय है।
धन्यवाद, आपका उदाहरण इसे स्पष्ट करता है। –
Mehrdad पहले से ही अपने सभी सवालों का जवाब है, लेकिन सिर्फ # 1 पर विस्तृत करने के - अंतर कोड की राशि है जो आप लिखने की ज़रूरत है।
class Point
{
private readonly int x, y;
public int X { get { return x; } }
public int Y { get { return y; } }
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
var p = new Point(1, 2);
आप केवल यह एक छोटा सा कम करने के लिए स्वत: गुण इस्तेमाल कर सकते हैं, लेकिन फिर अचल स्थिति वर्ग परिभाषा के अंदर कोड के लिए लागू नहीं किया जाता, उदाहरण के लिए, यहाँ परिभाषा और नमूना सी # में एक केवल पढ़ने के लिए बिंदु के फायदा नहीं है अपने ग्राहकों के लिए।
एफ # में, आप बस लिखना चाहते हैं:
type Point = { x: int; y: int }
let p = { x = 1; y = 2 }
और अगर आप चाहते थे यह परिवर्तनशील होने के लिए:
type Point = { mutable x: int; mutable y: int }
let p = { x = 1; y = 2 }
p.x <- 3
p.y <- 4
नमूना कोड पावेल के लिए धन्यवाद। –
बीटीडब्ल्यू यह मामूली है लेकिन पी.एक्स को पी.एक्स <- 3, और पी.एक्स = 3 की तरह क्यों बदला जाना चाहिए? या आप ऐसा करने के लिए = चिह्न का उपयोग कर सकते हैं? बस टाइप करना मुश्किल लगता है <-, लेकिन शायद यह मैं हूं। –
जब भी आप असाइनमेंट (कुछ म्यूटेबल) के माध्यम से कोई मान बदलते हैं तो आपको <- – gradbot
मुझे लगता है कि आप एक बहुत विस्तृत सुविधा के लिए इस पर देख रहे हैं एक दृश्य का फीचर बिंदु।
मैं इसे कैसे डेवलपर की वास्तविक प्रोग्रामिंग मन सेट को प्रभावित करता है पर होने की कार्यात्मक प्रोग्रामिंग भाषाओं की डिफ़ॉल्ट रूप से अचल स्थिति का प्रमुख लाभ देखते हैं।जब उत्परिवर्तन डिफ़ॉल्ट होता है, तो प्रोग्रामिंग दिमाग सेट डेटा को म्यूट करके समाधान की दिशा में तैयार किया जाता है। जब अपरिवर्तनीयता डिफ़ॉल्ट होती है, तो प्रोग्रामिंग दिमाग सेट डेटा को बदलकर समाधान की दिशा में तैयार किया जाता है।
विस्तारित करने के लिए कि बाद वाला दिमाग सेट बेहतर क्यों है। डेटा को म्यूटेट करके प्रोग्राम विकसित करते समय, आप ठीक विवरण में फंस जाते हैं, इसलिए आपका ध्यान इस बात पर निर्भर करता है कि कार्यक्रम 'छोटे में' कैसे काम करता है। डेटा को बदलने के माध्यम से प्रोग्राम विकसित करते समय, आपको कई अच्छे विवरणों के बारे में चिंता करने की आवश्यकता नहीं है (जैसे कि आपके प्रोग्राम के अलग-अलग हिस्सों को एक-दूसरे के साथ कैसे बातचीत करना), और आपका ध्यान इस बात पर निर्भर करता है कि कार्यक्रम कैसे काम करता है लम्बा'। इसलिए, बाद के दिमाग ने डेवलपर को प्रोग्राम कैसे काम करता है, इस पर एक बेहतर और स्पष्ट 'बड़ी तस्वीर' रखने की दिशा में गियर सेट किया।
एक कार्यक्रम की अच्छी साफ 'बड़ी तस्वीर' होने के दौरान, कुछ मामलों में, वास्तविक जीवन की चिंताएं इससे अधिक हो सकती हैं। कुछ डेटा संरचनाएं (सरणी, बहु आयामी सरणी) नई प्रतियां बनाने की उच्च लागत की वजह से अपरिवर्तनीयता के लिए अच्छे उम्मीदवार नहीं हैं, इसलिए कार्यात्मक भाषाओं के साथ भी अपरिवर्तनीयता का उपयोग न करने पर कुछ सामान्य ज्ञान हमेशा लागू किया जाना चाहिए।
कार्यात्मक भाषा शुद्धतावादी तर्क था कि यह कोड भद्दा बनाना होगा: टिप्पणी का जवाब देने के
संपादित करें। मैं खुद को शुद्धवादी नहीं मानता, इसलिए मुझे ऐसा नहीं लगता; ठीक है, शायद एक दृश्य के सैद्धांतिक बिंदु से uglier।
एफ # एक अशुद्ध कार्यात्मक प्रोग्रामिंग भाषा है, इसलिए इसकी आवश्यकता होने पर यह उत्परिवर्तन का समर्थन करता है। आपके राज्य का हिस्सा म्यूटेबल होने के कारण आपके अधिकांश राज्य को अपरिवर्तनीय होने के लाभों को अमान्य नहीं किया जाता है।
ज्यादातर मामलों में, आप एक अलग (शुद्ध) डेटा संरचना का उपयोग करते हैं जहां आप सामान्य रूप से एक अनिवार्य भाषा में सरणी का उपयोग करेंगे। जैसे एक ट्यूपल, एक सूची या एक पेड़ (या एक पेड़ के शीर्ष पर एक सेट/नक्शा निर्माण; मानक पुस्तकालय आमतौर पर अच्छी समय जटिलता के साथ कार्यान्वयन के साथ आते हैं)।
और यदि आपको लगता है कि आपको वास्तव में एक म्यूटेबल सरणी (प्रदर्शन कारणों से) की आवश्यकता है, तो आपके पास यह उपलब्ध है, इसलिए कोई भी आपको उपयोग करने से रोक नहीं रहा है।
तो आप एक सरणी का उपयोग करने जैसे मुद्दों से कैसे निपटते हैं, जहां आपने कहा था कि हर बार एक नई प्रतिलिपि बनाने के लिए महंगा है। क्या यह उन हिस्सों में एफ # कोड uglier बनाता है? कोई भी उदाहरण वास्तव में सहायक होगा। –
जोन: यह आमतौर पर उपभोग करने वाला कोड uglier नहीं बनाता है; यह सिर्फ 'newarr = mangle (oldarr)' जैसा दिखता है। हालांकि हर बार एक नई प्रतिलिपि बनाने के लिए महंगा है, लेकिन संरचना संरचना साझा करके अपरिवर्तनीयता का लाभ उठाने के लिए डेटा संरचनाएं डिजाइन कर सकती हैं; उदाहरण के लिए, यदि आपने सूची ए = (3, 2, 1) और सूची बी = (4, 3, 2, 1) से लिंक किया है, और दोनों अपरिवर्तनीय हैं, तो सूची बी को 4 से दर्शाया जा सकता है और फिर सिर पर एक सूचक ए के समान पेड़ के साथ किया जा सकता है। – mquander
ध्यान दें कि, जाहिर है, यदि आप एक परिवर्तनीय था, तो आप उस चाल को नहीं खींच सके, क्योंकि यदि आपने ए को बदल दिया है, तो बी के संदर्भ वाले किसी को भी यह पता चलेगा कि बी भी अलग था। – mquander
जैसा कि अन्य ने उल्लेख किया है, अपरिवर्तनीय डेटा का उपयोग करने के कुछ महत्वपूर्ण लाभ हैं। कुछ नाम करने के लिए:
- बनता - यह कार्यक्रम है कि परिणाम की गणना करता है और अपरिवर्तनीय डेटा संरचना में यह रिटर्न parallelize आसान है।
- कोड को समझना - यदि आप अपरिवर्तनीय डेटा का उपयोग कर प्रोग्राम लिखते हैं, तो केवल एक चीज कोड का एक टुकड़ा परिणाम लौटने के लिए कर सकता है - इससे प्रोग्राम अधिक पठनीय हो जाता है, क्योंकि आप देखते हैं कि इनपुट का विश्लेषण करके कोई फ़ंक्शन/विधि क्या करती है & आउटपुट
तकनीकी रूप से सीकिंग, आप सी # और एफ # दोनों में एक ही अपरिवर्तनीय डेटा संरचना लिख सकते हैं। समस्या यह है कि एफ # आपको ऐसा करने के लिए प्रोत्साहित करता है, जबकि सी # में वास्तविक अपरिवर्तनीय डेटा स्ट्रक्चर लिखना थोड़ा दर्दनाक है। इसका मतलब है कि एफ # कोड लिखते समय, आप अधिक संभावनाएं लिख सकते हैं अपरिवर्तनीय संरचनाएं (क्योंकि यह आसान है!) और आप उत्परिवर्तन का उपयोग करेंगे (जो कि F # में भी संभव है) केवल तभी जब आपको वास्तव में इसकी आवश्यकता होगी (यह कठिन है!)
डिफ़ॉल्ट रूप से अपरिवर्तनीय प्रकार घोषित करने के अलावा, F # में कुछ अच्छी सुविधाएं भी हैं जो उनके साथ काम करना आसान बनाती हैं।उदाहरण के लिए जब रिकॉर्ड के साथ काम:
type MyRect = { X : int; Y : int; Width : int; Height : int }
let r = { X = 0; Y = 0; Width = 200; Height = 100 }
// You'll often need to create clone with one field changed:
let rMoved1 = { X = 123; Y = r.Y; Width = r.Width; Height = r.Height }
// The same thing can be written using 'with' keyword:
let rMoved2 = { r with X = 123 }
तुम भी सी # में एक ही बात लिख सकते हैं, लेकिन आप विधि WithX
कि संशोधित X
क्षेत्र के साथ एक क्लोन देता है, WithY
, WithWidth
साथ अपरिवर्तनीय डेटा संरचना घोषित करने के लिए की आवश्यकता होगी,
class MyRect {
readonly int x, y, width, height;
MyRect WithX(int newX) {
return new MyRect(newX, y, width, height);
}
// etc...
}
इस संकलक से किसी भी मदद के बिना बहुत काम है: आदि ... यहाँ एक अधूरी उदाहरण है।
धन्यवाद, स्ट्रिंग मानों के बारे में भी क्या? मैंने .NET में स्ट्रिंग्स को सचमुच अपरिवर्तनीय नहीं सुना है। क्या एफ # समान स्ट्रिंग मानों का उपयोग करता है? –
.NET तार वास्तव में अपरिवर्तनीय हैं। उनके साथ काम करने के लिए सभी विधियां मूल एक को संशोधित किए बिना एक नई स्ट्रिंग लौटाती हैं (बस उपरोक्त मेरी एक्सएक्स विधि की तरह)। उदाहरण के लिए 'स्ट्रिंग s2 = s1.Substring (0, 4)' 's1' को संशोधित किए बिना एक नई स्ट्रिंग देता है।तो, एफ # सुरक्षित रूप से उसी स्ट्रिंग प्रकार का उपयोग .NET के रूप में कर सकता है। –
आपको एक एफ # अपरिवर्तनीय डेटा से क्या मिलता है जिसे आप सी # अपरिवर्तनीय डेटा से प्राप्त नहीं करते हैं?
पहला लाभ यह है कि एफ # फ़ंक्शन का कोई अन्य प्रभाव नहीं पड़ता इसके परिणाम को वापस करने के अलावा। कोई वैश्विक डेटा नहीं बदला गया है, कोई म्यूटेबल डेटा पर निर्भर नहीं है, और इसलिए आपको गारंटी है कि, बशर्ते आप अपरिवर्तनीय डेटा तक चिपके रहें, वही कॉल एक ही परिणाम, भरोसेमंद, हर बार उत्पन्न करता है। क्योंकि यह आपके कोड को समझने के लिए आसान बना देता है
यह पहली लाभ, अपने आप में पहले से ही अच्छा है, लेकिन क्योंकि एफ # कार्यों में बड़े लाभ किक सुरक्षित रूप से बना हो सकता है। फ़ंक्शन संरचना द्वारा प्रोग्रामिंग पुन: प्रयोज्य भागों के साथ प्रोग्राम करने के लिए एक अविश्वसनीय रूप से शक्तिशाली, मॉड्यूलर तरीका साबित होता है। और आप वास्तव में शक्तिशाली भागों का निर्माण कर सकते हैं जिन्हें कई अलग-अलग तरीकों से एक साथ रखा जा सकता है, ताकि आप कम कोड वाले अधिक प्रोग्राम लिख सकें।
ये विचार जॉन ह्यूजेस के ऐतिहासिक पेपर Why Functional Programming Matters में कभी भी बेहतर समझाए गए हैं। जॉन बताते हैं कि उत्परिवर्तन की क्षमता को हटाने से वास्तव में भाषा को अभिव्यक्तिपूर्ण शक्ति मिलती है। अखबार को पढ़ो!
आप से है कि आप एक सी # अपरिवर्तनीय डेटा से नहीं मिलता है एक एफ # अपरिवर्तनीय डेटा क्या मिलता है?
एफ # आपको आसानी से अपरिवर्तनीय डेटा की संशोधित प्रतियां बनाने की अनुमति देता है, यह बहुत कठिन और सी # से उपभोग करने वाला समय है। एफ # में एक रिकॉर्ड बनाने पर विचार करें:
type Person = { FirstName: string; MiddleName: string; LastName: string }
let me = { FirstName = "Robert"; MiddleName = "Frederick"; LastName = "Pickering" }
मैं अंतिम नाम क्षेत्र, एफ # में मैं एक प्रति कीवर्ड "के साथ" का उपयोग कर बनाने के द्वारा यह कर सकते हैं बदल चाहता था कहते हैं:
let me' = { me with LastName = "Townson" }
यदि आप चाहते थे सी # में ऐसा करने के लिए आपको उन तरीकों को बनाना होगा जो प्रत्येक फ़ील्ड को एक नई संरचना में कॉपी करते हैं और एक मजबूत संभावना है कि आप खेतों को मिश्रित कर लेंगे।
संग्रह के साथ अन्य उपयुक्त फायदे हैं। उदाहरण के लिए सी # अपरिवर्तनीय ReadOnlyCollection का समर्थन करता है। हालांकि हर बार जब आप इस संग्रह में एक नया आइटम जोड़ना चाहते हैं तो आपको पूरे संग्रह की एक प्रति बनाना होगा। सूची में F # बिल्ड आपको इसकी एक प्रति बनाये बिना सूची के अंत में एक नया आइटम जोड़ने की अनुमति देता है, यानी परिणामस्वरूप सूची वास्तव में पुरानी सूची में से अधिकांश साझा करेगी। यानी .:
let myList = [3; 2; 1]
let myList' = 4 :: myList
जब "MyList", "MyList" के पूरे अपरिवर्तित संरक्षित है और "4" जोड़ा जाता है करने के लिए यह सिर है "MyList बनाने के लिए '' का निर्माण।
धन्यवाद। 'मेरी सूची देने के बाद आप किस प्रतीक का इस्तेमाल करते हैं'? –
यह एक एकल उद्धरण चिह्न है, यह पहचानकर्ता नाम का सिर्फ एक हिस्सा है। एफ # में इसे अक्सर मुख्य प्रतीक http://en.wikipedia.org/wiki/Prime_(symbol) के स्थान पर उपयोग किया जाता है, जिसका मतलब पहले घोषित पहचानकर्ता का एक परिवर्तित संस्करण है। – Robert
तकनीकी रूप से, आप एफएफ या सी # में प्रतिबिंब के माध्यम से अपरिवर्तनीय गुणों का समर्थन करने वाले (निजी) फ़ील्ड को बदल सकते हैं - यदि आपके कोड में पहुंच-योग्यता जांच को ओवरराइड करने के लिए पर्याप्त अनुमतियां हैं। –
@ पावेल: वास्तव में। "मेमोरी हैक" द्वारा मेरा मतलब अप्रत्यक्ष रूप से सामान बदलने की व्यापक समझ थी। –
धन्यवाद, इसलिए एफ # आईएल में एक नया कीवर्ड का उपयोग करता है जो सी # समझता है जो वास्तव में अपरिवर्तनीय मान को चिह्नित करता है? –