F # और C # दोनों से उपयोग के लिए F # लाइब्रेरी डिजाइन करने के लिए सबसे अच्छा तरीका


113

मैं F # में एक लाइब्रेरी डिजाइन करने की कोशिश कर रहा हूं। पुस्तकालय F # और C # दोनों से उपयोग के लिए अनुकूल होना चाहिए ।

और यह वह जगह है जहां मैं थोड़ा फंस गया हूं। मैं इसे F # फ्रेंडली बना सकता हूं, या मैं इसे C # फ्रेंडली बना सकता हूं, लेकिन समस्या यह है कि इसे दोनों के लिए फ्रेंडली कैसे बनाया जाए।

यहाँ एक उदाहरण है। कल्पना कीजिए कि मेरे पास F # में निम्न कार्य है:

let compose (f: 'T -> 'TResult) (a : 'TResult -> unit) = f >> a

यह F # से पूरी तरह से प्रयोग करने योग्य है:

let useComposeInFsharp() =
    let composite = compose (fun item -> item.ToString) (fun item -> printfn "%A" item)
    composite "foo"
    composite "bar"

C # में, composeफ़ंक्शन में निम्न हस्ताक्षर हैं:

FSharpFunc<T, Unit> compose<T, TResult>(FSharpFunc<T, TResult> f, FSharpFunc<TResult, Unit> a);

लेकिन निश्चित रूप से, मैं FSharpFuncहस्ताक्षर नहीं करना चाहता , जो मैं चाहता हूं Funcऔर Actionइसके बजाय, इस तरह है:

Action<T> compose2<T, TResult>(Func<T, TResult> f, Action<TResult> a);

इसे प्राप्त करने के लिए, मैं compose2इस तरह से फंक्शन बना सकता हूं :

let compose2 (f: Func<'T, 'TResult>) (a : Action<'TResult> ) = 
    new Action<'T>(f.Invoke >> a.Invoke)

अब, यह C # में पूरी तरह से प्रयोग करने योग्य है:

void UseCompose2FromCs()
{
    compose2((string s) => s.ToUpper(), Console.WriteLine);
}

लेकिन अब हमें compose2F # का उपयोग करने में समस्या है ! अब मैं रैप करने के लिए सभी मानक एफ # है funsमें Funcऔर Actionइस तरह,:

let useCompose2InFsharp() =
    let f = Func<_,_>(fun item -> item.ToString())
    let a = Action<_>(fun item -> printfn "%A" item)
    let composite2 = compose2 f a

    composite2.Invoke "foo"
    composite2.Invoke "bar"

प्रश्न: हम F # और F # दोनों उपयोगकर्ताओं के लिए F # में लिखी गई लाइब्रेरी के लिए प्रथम श्रेणी का अनुभव कैसे प्राप्त कर सकते हैं?

अब तक, मैं इन दो दृष्टिकोणों से बेहतर कुछ भी नहीं कर सका:

  1. दो अलग-अलग असेंबली: एक एफ # उपयोगकर्ताओं के लिए लक्षित है, और दूसरा सी # उपयोगकर्ताओं के लिए।
  2. एक असेंबली लेकिन अलग नामस्थान: एक एफ # उपयोगकर्ताओं के लिए, और दूसरा सी # उपयोगकर्ताओं के लिए।

पहले दृष्टिकोण के लिए, मैं ऐसा कुछ करूंगा:

  1. F # प्रोजेक्ट बनाएं, इसे FooBarFs कहें और FooBarFs.dll में संकलित करें।

    • लाइब्रेरी को विशुद्ध रूप से F # उपयोगकर्ताओं को लक्षित करें।
    • .Fsi फ़ाइलों से अनावश्यक सब कुछ छिपाएँ।
  2. एक और F # प्रोजेक्ट बनाएं, FooBarCs को कॉल करें और FooFar.dll में संकलित करें

    • स्रोत स्तर पर पहले F # प्रोजेक्ट का पुन: उपयोग करें।
    • .Fsi फ़ाइल बनाएँ जो उस परियोजना से सब कुछ छुपाता है।
    • .Fsi फ़ाइल बनाएँ जो C # तरीके से लाइब्रेरी को उजागर करती है, नाम, नामस्थान आदि के लिए C # मुहावरों का उपयोग करते हुए।
    • ऐसे रैपर बनाएं जो कोर लाइब्रेरी को सौंपते हैं, जहां आवश्यक हो रूपांतरण करते हैं।

मुझे लगता है कि नामस्थान के साथ दूसरा दृष्टिकोण उपयोगकर्ताओं को भ्रमित कर सकता है, लेकिन फिर आपके पास एक विधानसभा है।

प्रश्न: इनमें से कोई भी आदर्श नहीं है, शायद मुझे किसी प्रकार के संकलक ध्वज / स्विच / विशेषता या किसी प्रकार की चाल याद आ रही है और ऐसा करने का एक बेहतर तरीका है?

सवाल: क्या किसी और ने भी कुछ ऐसा ही हासिल करने की कोशिश की है और अगर आपने ऐसा किया तो कैसे किया?

संपादित करें: स्पष्ट करने के लिए, सवाल केवल फ़ंक्शंस और प्रतिनिधियों के बारे में नहीं है, बल्कि F # लाइब्रेरी के साथ C # उपयोगकर्ता का समग्र अनुभव है। इसमें नाम स्थान, नामकरण परंपराएँ, मुहावरे और ऐसे प्रकार शामिल हैं जो C # के मूल निवासी हैं। मूल रूप से, एक C # उपयोगकर्ता को यह पता लगाने में सक्षम नहीं होना चाहिए कि पुस्तकालय F # में लेखक था। और इसके विपरीत, एक F # उपयोगकर्ता को C # लाइब्रेरी से निपटने का मन करना चाहिए।


संपादित करें 2:

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

मुझे और अधिक ठोस उदाहरण प्रदान करते हैं। मैंने सबसे उत्कृष्ट F # घटक डिज़ाइन दिशानिर्देश दस्तावेज़ (इसके लिए कई धन्यवाद @gradbot!) के माध्यम से पढ़ा है । दस्तावेज़ में दिए गए दिशानिर्देश, यदि उपयोग किए जाते हैं, तो कुछ मुद्दों को संबोधित करते हैं, लेकिन सभी नहीं।

दस्तावेज़ को दो मुख्य भागों में विभाजित किया गया है: 1) एफ # उपयोगकर्ताओं को लक्षित करने के लिए दिशानिर्देश; और # 2 सी # उपयोगकर्ताओं को लक्षित करने के लिए दिशानिर्देश। कहीं भी यह ढोंग करने का प्रयास नहीं करता है कि एक समान दृष्टिकोण रखना संभव है, जो वास्तव में मेरे प्रश्न को प्रतिध्वनित करता है: हम एफ # को लक्षित कर सकते हैं, हम सी # को लक्षित कर सकते हैं, लेकिन दोनों को लक्षित करने के लिए व्यावहारिक समाधान क्या है?

याद दिलाने के लिए, लक्ष्य F # में एक लाइब्रेरी है, और जिसका उपयोग F # और C # दोनों भाषाओं में मुहावरेदार तरीके से किया जा सकता है ।

यहां कीवर्ड मुहावरेदार है । मुद्दा सामान्य अंतर नहीं है जहां विभिन्न भाषाओं में पुस्तकालयों का उपयोग करना संभव है।

अब उदाहरण के लिए, जिसे मैं सीधे एफ # घटक डिज़ाइन दिशानिर्देशों से लेता हूं ।

  1. मॉड्यूल + फ़ंक्शन (F #) बनाम नामस्थान + प्रकार + फ़ंक्शन

    • F #: अपने प्रकार और मॉड्यूल शामिल करने के लिए नामस्थान या मॉड्यूल का उपयोग करें। मुहावरों का उपयोग मॉड्यूल में कार्य करने के लिए होता है, जैसे:

      // library
      module Foo
      let bar() = ...
      let zoo() = ...
      
      
      // Use from F#
      open Foo
      bar()
      zoo()
      
    • C #: वैनिला .NET API के लिए अपने घटकों के लिए प्राथमिक संगठनात्मक संरचना के रूप में नामस्थान, प्रकार और सदस्यों का उपयोग करें।

      यह F # दिशानिर्देश के साथ असंगत है, और उदाहरण के लिए C # उपयोगकर्ताओं को फिट करने के लिए फिर से लिखना होगा:

      [<AbstractClass; Sealed>]
      type Foo =
          static member bar() = ...
          static member zoo() = ...
      

      हालांकि ऐसा करने से, हम F # से मुहावरेदार उपयोग को तोड़ते हैं क्योंकि हम अब इसका उपयोग नहीं कर सकते हैं barऔर zooइसके साथ उपसर्ग किए बिना Foo

  2. टुपल्स का उपयोग

    • एफ #: वापसी मूल्यों के लिए उपयुक्त होने पर टुपल्स का उपयोग करें।

    • C #: वनीला .NET एपीआई में रिटर्न वैल्यू के रूप में ट्यूपल्स के उपयोग से बचें।

  3. async

    • F #: F # API सीमाओं पर Async प्रोग्रामिंग के लिए Async का उपयोग करें।

    • C #: अतुल्यकालिक प्रोग्रामिंग मॉडल (BeginFoo, EndFoo) का उपयोग करके अतुल्यकालिक संचालन को उजागर करें, या F # Async ऑब्जेक्ट्स के बजाय .NET कार्य (टास्क) को वापस करने के तरीकों के रूप में करें।

  4. का उपयोग Option

    • F #: अपवाद बढ़ाने के बजाय रिटर्न प्रकारों के लिए विकल्प मानों का उपयोग करने पर विचार करें (F # -facing कोड के लिए)।

    • वैनिला .NET एपीआई में F # विकल्प मान (विकल्प) को वापस करने के बजाय TryGetValue पैटर्न का उपयोग करने पर विचार करें, और तर्क के रूप में F # विकल्प मान लेने से अधिक अधिभार विधि को प्राथमिकता दें।

  5. भेदभाव रहित संघ

    • एफ #: वृक्ष-संरचित डेटा बनाने के लिए वर्ग पदानुक्रम के विकल्प के रूप में भेदभाव वाली यूनियनों का उपयोग करें

    • C #: इसके लिए कोई विशेष दिशानिर्देश नहीं है, लेकिन भेदभाव वाली यूनियनों की अवधारणा C # के लिए विदेशी है

  6. करी कार्य

    • एफ #: करी कार्य एफ # के लिए मुहावरेदार हैं

    • सी #: वेनिला .NET एपीआई में मापदंडों की करी का उपयोग न करें।

  7. अशक्त मूल्यों के लिए जाँच कर रहा है

    • F #: यह F # के लिए मुहावरेदार नहीं है

    • C #: वेनिला .NET एपीआई सीमाओं पर शून्य मानों के लिए जाँच पर विचार करें।

  8. एफ # प्रकार के उपयोग list, map, set, आदि

    • F #: इनको F # में इस्तेमाल करना मुहावरेदार है

    • C #: .NET संग्रह इंटरफ़ेस प्रकारों का उपयोग करने पर विचार करें मापदंडों के लिए IEnumerable और IDEDIA और वेनिला .NET एपीआई में मान लौटाएं। ( यानी उपयोग नहीं करते हैं एफ # list, map,set )

  9. फ़ंक्शन प्रकार (स्पष्ट एक)

    • एफ #: मान के रूप में एफ # कार्यों का उपयोग एफ # के लिए मुहावरेदार है, जाहिर है

    • C #: वेनिला .NET API में F # फंक्शन टाइप्स को वरीयता में .NET डेलिगेट टाइप्स का उपयोग करें।

मुझे लगता है कि ये मेरे प्रश्न की प्रकृति को प्रदर्शित करने के लिए पर्याप्त होना चाहिए।

संयोग से, दिशानिर्देशों का आंशिक उत्तर भी है:

... वेनिला .NET पुस्तकालयों के लिए उच्च-क्रम के तरीकों को विकसित करते समय एक सामान्य कार्यान्वयन रणनीति एफ # फ़ंक्शन प्रकारों का उपयोग करके सभी कार्यान्वयन को लेखक के लिए है, और फिर वास्तविक एफ # कार्यान्वयन के ऊपर एक पतली बहाना के रूप में प्रतिनिधियों का उपयोग करके सार्वजनिक एपीआई बनाएं।

संक्षेपित करते हुए।

एक निश्चित उत्तर है: कोई संकलक चालें नहीं हैं जो मैंने याद किया

दिशानिर्देशों के अनुसार, ऐसा लगता है कि F # के लिए संलेखन और फिर .NET के लिए एक मुखौटा आवरण बनाना एक उचित रणनीति है।

इसके बाद व्यावहारिक कार्यान्वयन के बारे में सवाल बना रहता है:

  • अलग-अलग विधानसभाएं? या

  • विभिन्न नामस्थान?

यदि मेरी व्याख्या सही है, तो टॉमस का सुझाव है कि अलग नामस्थानों का उपयोग करना पर्याप्त होना चाहिए, और एक स्वीकार्य समाधान होना चाहिए।

मुझे लगता है कि मैं इस बात से सहमत हूं कि दिए गए नामस्थानों की पसंद ऐसी है कि यह .NET / C # उपयोगकर्ताओं को आश्चर्यचकित या भ्रमित नहीं करता है, जिसका अर्थ है कि उनके लिए नाम स्थान संभवतः यह देखना चाहिए कि यह उनके लिए प्राथमिक नाम स्थान है। F # उपयोगकर्ताओं को F # -specific नाम स्थान चुनने का भार उठाना होगा। उदाहरण के लिए:

  • FSharp.Foo.Bar -> F # लाइब्रेरी के लिए नामस्थान

  • Foo.Bar -> .NET रैपर के लिए नाम स्थान, C # के लिए मुहावरेदार


8
कुछ हद तक प्रासंगिक research.microsoft.com/en-us/um/cambridge/projects/fsharp/…
gradbot

प्रथम श्रेणी के कार्यों से गुजरने के अलावा, आपकी चिंताएं क्या हैं? एफ # पहले से ही अन्य भाषाओं से एक सहज अनुभव प्रदान करने की दिशा में एक लंबा रास्ता तय करता है।
डैनियल

पुन: आपका संपादन, मैं अभी भी स्पष्ट नहीं हूं कि आप ऐसा क्यों सोचते हैं कि F # में लिखा गया एक पुस्तकालय C # से गैर-मानक दिखाई देगा। अधिकांश भाग के लिए, F # C # कार्यक्षमता का सुपरसेट प्रदान करता है। पुस्तकालय को स्वाभाविक महसूस करना ज्यादातर सम्मेलन का विषय है, जो कि कोई भी बात नहीं है कि आप किस भाषा का उपयोग कर रहे हैं। यह सब कहने के लिए, F # आपको ऐसा करने के लिए आवश्यक सभी उपकरण प्रदान करता है।
डैनियल

ईमानदारी से भले ही आप एक कोड नमूना शामिल करते हैं, आप एक काफी खुले-समाप्त प्रश्न पूछ रहे हैं। आप "एफ # लाइब्रेरी के साथ सी # उपयोगकर्ता के समग्र अनुभव" के बारे में पूछते हैं, लेकिन आप जो एकमात्र उदाहरण देते हैं वह कुछ ऐसा है जो वास्तव में किसी भी अनिवार्य भाषा में अच्छी तरह से समर्थित नहीं है । प्रथम श्रेणी के नागरिकों के रूप में कार्य करना व्यवहारिक प्रोग्रामिंग का एक सुंदर केंद्रीय सिद्धांत है - जो अधिकांश अनिवार्य भाषाओं में खराब होता है।
ओनोरियो कैटेनेशियो

2
@KomradeP .: अपने EDIT 2 के संबंध में, FSharpx इंटरऑपरेबिलिटी को अधिक प्रतीत करने के लिए कुछ साधन प्रदान करता है। आप इस उत्कृष्ट ब्लॉग पोस्ट में कुछ संकेत पा सकते हैं ।
पैड

जवाबों:


40

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

F # का उपयोग करते समय, मूल रूप से दो प्रकार के पुस्तकालय हैं जिन्हें आप लिख सकते हैं:

  • F # लाइब्रेरी को F # से ही उपयोग करने के लिए डिज़ाइन किया गया है , इसलिए यह सार्वजनिक इंटरफ़ेस एक कार्यात्मक शैली में लिखा गया है (F # फ़ंक्शन प्रकार, ट्यूपल्स, भेदभाव किए गए यूनियनों आदि का उपयोग करके)

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

अपने प्रश्न में, आप पूछ रहे हैं कि फ़ंक्शन रचना को .NET लाइब्रेरी के रूप में कैसे उजागर किया जाए, लेकिन मुझे लगता है कि आपके जैसे फ़ंक्शन compose.NET लाइब्रेरी पॉइंट से बहुत कम स्तर की अवधारणाएं हैं। आप उनके साथ काम करने के तरीकों के रूप में उजागर कर सकते हैं Funcऔर Action, लेकिन संभवत: यह नहीं है कि आप पहली बार में एक सामान्य .NET पुस्तकालय कैसे डिजाइन करेंगे (शायद आप बिल्डर पैटर्न का उपयोग करेंगे या ऐसा कुछ करेंगे)।

कुछ मामलों में (यानी जब संख्यात्मक पुस्तकालयों को डिजाइन करना जो वास्तव में .NET पुस्तकालय शैली के साथ अच्छी तरह से फिट नहीं होते हैं), यह एक पुस्तकालय डिजाइन करने के लिए एक अच्छा अर्थ देता है जो एक ही पुस्तकालय में F # और .NET शैलियों दोनों को मिलाता है । ऐसा करने का सबसे अच्छा तरीका सामान्य एफ # (या सामान्य .NET) एपीआई है और फिर दूसरी शैली में प्राकृतिक उपयोग के लिए रैपर प्रदान करना है। रैपर एक अलग नामस्थान (जैसे MyLibrary.FSharpऔर MyLibrary) में हो सकते हैं।

आपके उदाहरण में, आप F # कार्यान्वयन को अंदर छोड़ सकते हैं MyLibrary.FSharpऔर फिर .NET (C # -friendly) रैपर (कोड के समान जो डैनियल पोस्ट किया है) MyLibraryको कुछ वर्ग के स्थैतिक विधि के रूप में नामस्थान में जोड़ सकते हैं । लेकिन फिर से, .NET लाइब्रेरी में फंक्शन कंपोजीशन की तुलना में अधिक विशिष्ट API होगा।


1
एफ # कंपोनेंट डिज़ाइन गाइडलाइन्स को अब यहां
Jan Schiefer

19

आपको केवल फ़ंक्शन मान (आंशिक रूप से लागू किए गए कार्य, आदि) Funcया उसके साथ रैप करना होगा Action, बाकी स्वचालित रूप से परिवर्तित हो जाते हैं। उदाहरण के लिए:

type A(arg) =
  member x.Invoke(f: Func<_,_>) = f.Invoke(arg)

let a = A(1)
a.Invoke(fun i -> i + 1)

तो यह उपयोग करने के लिए समझ में आता है Func/ Actionजहां लागू हो। क्या यह आपकी चिंताओं को खत्म करता है? मुझे लगता है कि आपके प्रस्तावित समाधान अत्यधिक जटिल हैं। आप अपनी पूरी लाइब्रेरी को F # में लिख सकते हैं और F # और C # से दर्द-मुक्त का उपयोग कर सकते हैं (मैं इसे हर समय करता हूं)।

साथ ही, एफ # इंटरऑपरेबिलिटी के मामले में सी # से अधिक लचीला है, इसलिए आमतौर पर पारंपरिक .NET शैली का पालन करना सबसे अच्छा है जब यह एक चिंता का विषय है।

संपादित करें

मुझे लगता है कि अलग-अलग नामस्थानों में दो सार्वजनिक इंटरफेस बनाने के लिए आवश्यक कार्य, केवल तभी वारंट किए जाते हैं जब वे पूरक होते हैं या F # कार्यक्षमता C # से उपयोग करने योग्य नहीं होती है (जैसे कि इनलाइन किए गए कार्य, जो F # -pecec मेटाडेटा पर निर्भर करते हैं)।

अपनी बातों को बदले में लेना:

  1. मॉड्यूल + letबाइंडिंग और कंस्ट्रक्टर-कम प्रकार + स्थैतिक सदस्य C # में बिल्कुल समान दिखाई देते हैं, इसलिए यदि आप कर सकते हैं तो मॉड्यूल के साथ जाएं। आप CompiledNameAttributeसदस्यों को C # -अभिमानी नाम देने के लिए उपयोग कर सकते हैं ।

  2. मैं गलत हो सकता हूं, लेकिन मेरा अनुमान है कि घटक दिशानिर्देशों को System.Tupleढांचे में जोड़े जाने से पहले लिखा गया था । (पहले के संस्करणों में एफ # परिभाषित किया गया यह स्वयं का प्रकार है।) यह तब से है जब Tupleतुच्छ प्रकारों के लिए सार्वजनिक इंटरफ़ेस में उपयोग करना अधिक स्वीकार्य हो गया है ।

  3. यह वह जगह है जहां मुझे लगता है कि आपके पास सी # तरीका है क्योंकि एफ # के साथ अच्छा खेलता है Taskलेकिन सी # के साथ अच्छा नहीं खेलता है Async। आप Async.StartAsTaskसार्वजनिक रूप से लौटने से पहले आंतरिक रूप से कॉल कर सकते हैं ।

  4. nullC # से उपयोग के लिए API विकसित करते समय आलिंगन एकमात्र सबसे बड़ी कमी हो सकती है। अतीत में, मैंने आंतरिक एफ # कोड में शून्य पर विचार करने से बचने के लिए सभी प्रकार की कोशिशें कीं, लेकिन अंत में, [<AllowNullLiteral>]नल के लिए सार्वजनिक निर्माणकर्ताओं के साथ प्रकारों को चिह्नित करना और आर्गन की जांच करना सबसे अच्छा था । यह इस संबंध में C # से बदतर नहीं है।

  5. विभेदित संघ आमतौर पर वर्ग पदानुक्रम के लिए संकलित किए जाते हैं, लेकिन हमेशा C # में अपेक्षाकृत अनुकूल प्रतिनिधित्व होता है। मैं कहूंगा, उन्हें चिह्नित करें [<AllowNullLiteral>]और उनका उपयोग करें।

  6. करी कार्य फ़ंक्शन मान का उत्पादन करते हैं , जिसका उपयोग नहीं किया जाना चाहिए।

  7. मैंने पाया कि सार्वजनिक इंटरफेस पर पकड़े जाने पर निर्भर रहने और इसे आंतरिक रूप से अनदेखा करने की तुलना में अशक्त को गले लगाना बेहतर था। YMMV।

  8. यह उपयोग करने के लिए भावना का एक बहुत बनाता है list/ map/ setआंतरिक रूप से। वे सभी सार्वजनिक इंटरफ़ेस के माध्यम से उजागर किए जा सकते हैं IEnumerable<_>। इसके अलावा, seq, dict, और Seq.readonlyअक्सर उपयोगी होते हैं।

  9. # 6 देखें।

आप कौन सी रणनीति लेते हैं, यह आपके पुस्तकालय के प्रकार और आकार पर निर्भर करता है, लेकिन मेरे अनुभव में, अलग-अलग एपीआई बनाने की तुलना में एफ # और सी # के बीच के मधुर स्थान को कम काम की आवश्यकता है।


हां मैं देख सकता हूं कि चीजों को काम करने के कुछ तरीके हैं, मैं पूरी तरह से आश्वस्त नहीं हूं। पुन: मॉड्यूल। यदि आपके पास है module Foo.Bar.Zooतो C # में यह class Fooनामस्थान में होगा Foo.Bar। हालाँकि, यदि आपके पास जैसे नेस्टेड मॉड्यूल हैं module Foo=... module Bar=... module Zoo==, तो यह Fooआंतरिक कक्षाओं के साथ वर्ग उत्पन्न करेगा Barऔर Zoo। पुन IEnumerable: यह स्वीकार्य नहीं हो सकता है जब हमें वास्तव में नक्शे और सेट के साथ काम करने की आवश्यकता होती है। पुन nullमूल्यों और AllowNullLiteral- एक कारण मैं एफ की तरह # है, क्योंकि मैं के थक गया हूँ nullसी # में, वास्तव में इसके साथ नापाक सब कुछ फिर से नहीं करना चाहेंगे!
फिलिप पी।

आम तौर पर इंटरॉप के लिए नेस्टेड मॉड्यूल पर नाम स्थान। पुन: अशक्त, मैं आपसे सहमत हूं, यह निश्चित रूप से इस पर विचार करने के लिए एक प्रतिगमन है, लेकिन अगर आपके एपीआई का उपयोग C # से किया जाएगा तो आपको कुछ करना होगा।
डैनियल

2

हालांकि यह शायद एक ओवरकिल होगा, आप मोन.ओसिल (यह मेलिंग सूची पर भयानक समर्थन है) का उपयोग करके एक आवेदन लिखने पर विचार कर सकते हैं जो आईएल स्तर पर रूपांतरण को स्वचालित करेगा। उदाहरण के लिए, आप F # -स्टाइल पब्लिक API का उपयोग करके F # में अपनी असेंबली को लागू करते हैं, तो टूल उस पर C # -ऑफ़रली रैपर जेनरेट करेगा।

उदाहरण के लिए, F # में आप C # की तरह उपयोग करने के बजाय स्पष्ट रूप से option<'T>( Noneविशेष रूप से) उपयोग करेंगे null। इस परिदृश्य के लिए एक रैपर जनरेटर लिखना काफी आसान होना चाहिए: रैपर विधि मूल विधि को लागू करेगी: यदि यह रिटर्न वैल्यू थी Some x, तो वापस लौटें x, अन्यथा वापस लौटें null

जब Tआप एक मूल्य प्रकार, यानी गैर-अशक्त होने पर मामले को संभालने की आवश्यकता होगी ; आपको रैपर विधि के रिटर्न वैल्यू को लपेटना होगा Nullable<T>, जिससे यह थोड़ा दर्दनाक हो।

फिर से, मुझे पूरा यकीन है कि इस तरह के उपकरण को अपने परिदृश्य में लिखने के लिए भुगतान करना होगा, हो सकता है सिवाय इसके कि आप इस तरह की लाइब्रेरी पर काम कर रहे हों (नियमित रूप से एफ # और सी # दोनों से बेकार)। किसी भी मामले में, मुझे लगता है कि यह एक दिलचस्प प्रयोग होगा, एक जिसे मैं कभी-कभी भी देख सकता हूं।


दिलचस्प लगता है। Mono.Cecilमूल रूप से F # असेंबली को लोड करने, मैपिंग की आवश्यकता वाली वस्तुओं को खोजने के लिए प्रोग्राम लिखने का उपयोग करने का मतलब होगा , और वे C # रैपर के साथ एक और असेंबली का उत्सर्जन कर रहे हैं? क्या मुझे यह अधिकार मिला?
फिलिप पी।

@Komrade P .: आप ऐसा कर सकते हैं, लेकिन यह बहुत अधिक जटिल है, क्योंकि तब आपको नई विधानसभा के सदस्यों को इंगित करने के लिए सभी संदर्भों को समायोजित करना होगा। यदि आप नए सदस्यों (रैपर) को मौजूदा F # -लेखित असेंबली में जोड़ते हैं तो यह बहुत सरल है।
ShdNx

2

ड्राफ्ट एफ # घटक डिजाइन दिशानिर्देश (अगस्त 2010)

अवलोकन यह दस्तावेज़ F # घटक डिज़ाइन और कोडिंग से संबंधित कुछ मुद्दों को देखता है। विशेष रूप से, इसमें शामिल हैं:

  • किसी भी .NET भाषा से उपयोग के लिए "वैनिला" .NET लाइब्रेरी डिजाइन करने के लिए दिशानिर्देश।
  • एफ # -to-F # पुस्तकालयों और एफ # कार्यान्वयन कोड के लिए दिशानिर्देश।
  • एफ # कार्यान्वयन कोड के लिए कोडिंग सम्मेलनों पर सुझाव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.