2010-03-08 3 views
7

मैं वर्तमान में एफ # और सामान्य रूप से कार्यात्मक प्रोग्रामिंग (सी # पृष्ठभूमि से) सीख रहा हूं और मेरे पास प्रोसेसिंग के दौरान .net सीएलआर ऑब्जेक्ट्स का उपयोग करने के बारे में एक सवाल है।आप एफ # में आसपास के .NET ऑब्जेक्ट मान कैसे पास करते हैं?

मेरी समस्या का वर्णन करने के लिए एक उदाहरण देने के लिए किया जाएगा सबसे अच्छा तरीका है:

let xml = new XmlDocument() 
      |> fun doc -> doc.Load("report.xml"); doc 

let xsl = new XslCompiledTransform() 
      |> fun doc -> doc.Load("report.xsl"); doc 

let transformedXml = 
    new MemoryStream() 
     |> fun mem -> xsl.Transform(xml.CreateNavigator(), null, mem); mem 

इस कोड .net वस्तुओं का उपयोग कर एक XSLT दस्तावेज़ के साथ एक XML दस्तावेज बदल देती है। नोट XslCompiledTransform.Load किसी ऑब्जेक्ट पर काम करता है, और शून्य लौटाता है। इसके अलावा XslCompiledTransform.Transform को मेमोरीस्ट्रीम ऑब्जेक्ट की आवश्यकता होती है और शून्य लौटाती है।

उपरोक्त रणनीति का उपयोग ऑब्जेक्ट को अंत (एमएम) में एक मूल्य वापस करने और कार्यात्मक प्रोग्रामिंग कार्य करने के लिए जोड़ना है।

हम एक के बाद यह एक क्या करना चाहते हैं जब हम अंत में एक वापसी मान के साथ प्रत्येक पंक्ति पर एक समारोह है:

let myFunc = 
    new XmlDocument("doc") 
    |> fun a -> a.Load("report.xml"); a 
    |> fun a -> a.AppendChild(new XmlElement("Happy")); a 

वहाँ एक और अधिक सही तरीका है (कार्यात्मक प्रोग्रामिंग के संदर्भ में) को संभालने के लिए .NET ऑब्जेक्ट्स और ऑब्जेक्ट्स जो अधिक ओओ पर्यावरण में बनाए गए थे?

जिस तरह से मैंने अंत में मूल्य वापस कर दिया था, उसके बाद इनलाइन कार्यों को हर जगह एक हैक की तरह लगता है और ऐसा करने का सही तरीका नहीं है।

किसी भी मदद की बहुत सराहना की जाती है!

उत्तर

10

एफ # के महान लाभों में से एक यह है कि यह आपको अन्य शैलियों (अर्थात् वस्तु-उन्मुख और अनिवार्य) के साथ कार्यात्मक प्रोग्रामिंग शैली को मिश्रित करने की अनुमति देता है। चूंकि अधिकांश .NET पुस्तकालय ऑब्जेक्ट उन्मुख और अनिवार्य हैं, इसलिए F # से .NET कार्यक्षमता तक पहुंचने का सबसे अच्छा तरीका केवल F # की अनिवार्य विशेषताओं का उपयोग करना है। इसका मतलब है कि .NET ऑब्जेक्ट्स के साथ काम करते समय, idiomatical F # कोड लगभग सी # की तरह दिखेगा।

EDIT: निम्नलिखित थोड़ा संशोधित उदाहरण दिखाता है कि एक्सएसएल रूपांतरण को उस फ़ंक्शन में कैसे लपेटना है जो इनपुट फ़ाइल का नाम और xsl फ़ाइल का नाम लेता है। यह रिटर्न MemoryStream जहां उत्पादन लिखा था:

let transformDocument inputFile xslFile = 
    let doc = new XmlDocument() 
    doc.Load(inputFile) 
    let xsl = new XslCompiledTransform() 
    xsl.Load(xslFile) 

    let mem = new MemoryStream() 
    xsl.Transform(xml.CreateNavigator(), null, mem) 
    mem 

और दूसरा उदाहरण:

let doc = new XmlDocument("doc") 
doc.Load("report.xml") 
doc.AppendNode(new XmlElement("Happy")) 

इसका मतलब यह नहीं है कि आप किसी भी तरह से कार्यात्मक शैली से दूर चालू कर देते हैं - देखते हैं .NET कक्षाओं के साथ काम करते समय कार्यात्मक शैली का उपयोग करने के कई अवसर। उदाहरण के लिए आप डेटा (या एक्सएमएल तत्व) के संग्रह को संसाधित करने के लिए Seq.filter और Seq.map (या अनुक्रम अभिव्यक्ति) जैसे उच्च-आदेश फ़ंक्शन का उपयोग कर सकते हैं। आप अभी भी उच्च-आदेश कार्यों का उपयोग करके अमूर्त लिख सकते हैं।

System.Xml नामस्थान बहुत जरूरी है, इसलिए कार्यात्मक शैली के लिए बहुत अधिक जगह नहीं है। हालांकि, आपके द्वारा एक्सएमएल में संग्रहीत डेटा जेनरेट करने वाला कोड पूरी तरह कार्यात्मक हो सकता है। LINQ से XML कक्षाओं (.NET 3.5+ में) को देखने के लायक हो सकता है, क्योंकि उन्हें अधिक कार्यात्मक-प्रोग्रामिंग-अनुकूल फैशन में डिज़ाइन किया गया है (क्योंकि उन्हें LINQ के साथ अच्छी तरह से काम करना चाहिए, जो कार्यात्मक भी है)।

+0

महान प्रतिक्रिया के लिए धन्यवाद :) क्या मैं कोड डाल सकता हूं (आपके द्वारा लिखे गए दूसरे उदाहरण को कहें) सभी एक ही फ़ंक्शन में जो दस्तावेज़ ऑब्जेक्ट देता है? – Russell

+0

हाँ, निश्चित रूप से! बाकी (अच्छे) कार्यात्मक कार्यक्रम से (बदसूरत) अनिवार्य बिट्स को छिपाने का यह सबसे अच्छा तरीका है। मैंने जवाब (पहला उदाहरण) संपादित किया, ताकि यह एक्सएसएल फाइलों का उपयोग कर एक्सएमएल फाइलों को बदलने के लिए एक सरल कार्य दिखाता है। –

+0

विस्तृत उदाहरण और स्पष्टीकरण के लिए उत्कृष्ट धन्यवाद! :) – Russell

9

पहले से ही उत्कृष्ट जवाब टॉमस के लिए एक और निफ्टी टिप जोड़ने के लिए, इन कार्यों करी के लिए एफ # लिए उसकी उपयोगिता, यहां तक ​​कि जरूरी कोडिंग तकनीक का उपयोग जरूरत पड़ने पर का एक अच्छा संकेत देने के लिए अवसर है।

उदाहरण 1 टॉमस इस्तेमाल किया एक xml दस्तावेज़ एक XSL दस्तावेज़ दिया बदलने के लिए किया गया था: this पोस्ट पढ़ने के बाद

let transformDocument inputFile xslFile = 
    let doc = new XmlDocument() 
    doc.Load(inputFile) 
    let xsl = new XslCompiledTransform() 
    xsl.Load(xslFile) 

    let mem = new MemoryStream() 
    xsl.Transform(xml.CreateNavigator(), null, mem) 
    mem 

, मैं एक कदम आगे जाना है और हमें इस समारोह करी करने की अनुमति के लिए एक रास्ता के बारे में सोचा। क्या इसका मतलब यह है (यदि हम चुनते हैं) है हम समारोह केवल एक XSL दस्तावेज़ पारित कर सकते हैं, यह एक समारोह है कि किसी भी एक्सएमएल दस्तावेज़ दिए गए निर्दिष्ट XSL दस्तावेज़ बदल सकते हैं वापस आ जाएगी:

let transform = 
    (fun xsl -> 
     let xsl_doc = new XslCompiledTransform() 
     xsl_doc.Load(string xsl) 

     (fun xml -> 
      let doc = new XmlDocument() 
      doc.Load(string xml) 
      let mem = new MemoryStream() 
      xsl_doc.Transform(doc.CreateNavigator(), null, mem) 
      mem 
     ) 
    ) 

तो हम निम्नलिखित कर सकता है:

let transform_report_xsl = transform "report.xsl" 
let transform_style_xsl = transform "style.xsl" 

transform_report_xsl "report.xml" 
transform_report_xsl "report2.xml" 
transform_style_xsl "page.xml" 
+1

यह एक महान उदाहरण है! आप वास्तव में मेरे मूल कार्य में केवल एक तर्क निर्दिष्ट कर सकते हैं (क्योंकि एफ # फ़ंक्शंस स्वचालित रूप से विवाहित होते हैं)। हालांकि, आपका संस्करण बहुत बेहतर है - जब आप इसे केवल एक पैरामीटर देते हैं, तो यह एक्सएसएल रूपांतरण लोड करेगा, इसलिए अलग-अलग एक्सएमएल फाइलों को प्रोसेस करना तेज होगा। यह चाल (या पैटर्न :-)) आमतौर पर _pre-computation_ कहा जाता है। –

+0

जानकारी के लिए धन्यवाद :) यह कार्यक्षमता को और भी अलग करता है (एक्सएसएल कोड को एक समारोह में और एक्सएमएल कोड को दूसरे में मजबूर करता है) जो इसे और अधिक पठनीय बनाता है। – Russell

+0

बस आज मैंने jQuery के साथ कुछ जावास्क्रिप्ट करते समय आसपास के कार्यों को पारित करने में इस समाधान के बारे में सोचा। रिटर्निंग फ़ंक्शन परिभाषा वास्तव में बहुत उपयोगी हो सकती है! – Russell

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