2008-10-13 6 views
6

मैं कोड है कि इस के समान दिखता है लिख रहा हूँ:आप एक गणक को कैसे डिजाइन करते हैं जो (सैद्धांतिक रूप से) वस्तुओं की एक अनंत राशि देता है?

public IEnumerable<T> Unfold<T>(this T seed) 
{ 
    while (true) 
    { 
     yield return [next (T)object in custom sequence]; 
    } 
} 

जाहिर है, इस विधि कभी नहीं लौटने के लिए जा रहा है। (सी # संकलक चुपचाप इस अनुमति देता है, जबकि आर # मुझे चेतावनी "समारोह रिटर्न कभी नहीं" देता है।)

सामान्य शब्दों में, यह बुरा एक प्रगणक कि मदों की एक अनंत संख्या देता है प्रदान करने के लिए डिजाइन है, बिना गणना करने के लिए एक रास्ता की आपूर्ति?

क्या इस परिदृश्य के लिए कोई विशेष विचार है? मेम? पर्फ़? अन्य गॉथस?

यदि हम हमेशा बाहर निकलने की स्थिति की आपूर्ति करते हैं, तो कौन से विकल्प हैं? उदाहरण के लिए:

  • प्रकार टी का एक उद्देश्य है कि समावेशी या विशेष सीमा
  • एक Predicate<T> continue (TakeWhile के रूप में करता है)
  • गिनती का प्रतिनिधित्व करता है (Take करता है)
  • ...

क्या हमें Unfold(...) के बाद Take(...)/TakeWhile(...) पर कॉल करने वाले उपयोगकर्ताओं पर भरोसा करना चाहिए? (शायद पसंदीदा विकल्प, क्योंकि यह मौजूदा लिंक ज्ञान का लाभ उठाता है।)

क्या आप इस प्रश्न का अलग-अलग जवाब देंगे यदि कोड सार्वजनिक एपीआई में प्रकाशित किया जा रहा था, या तो (जेनेरिक) या एक विशिष्ट कार्यान्वयन के रूप में यह पैटर्न?

+0

बीटीडब्ल्यू, आप अपने प्रश्न के संबंध में यह दिलचस्प पा सकते हैं: http://blogs.msdn.com/b/wesdyer/archive/2007/02/13/the-virtues-of-laziness.aspx – joce

उत्तर

7

जब तक आप बहुत स्पष्ट रूप से दस्तावेज करते हैं कि विधि कभी भी समाप्त नहीं होती है (विधि स्वयं ही बहुत जल्दी लौटती है) तो मुझे लगता है कि यह ठीक है। दरअसल, यह कुछ एल्गोरिदम को बहुत साफ कर सकता है। मुझे विश्वास नहीं है कि कोई महत्वपूर्ण स्मृति/पर्फ प्रभाव हैं - हालांकि यदि आप अपने इटरेटर के भीतर एक "महंगी" वस्तु का संदर्भ लेते हैं, तो वह संदर्भ कैप्चर किया जाएगा।

एपीआई का दुरुपयोग करने के हमेशा तरीके हैं: जब तक आपके दस्तावेज़ स्पष्ट हैं, मुझे लगता है कि यह ठीक है।

+0

इसके अलावा प्रलेखन, मुझे लगता है कि यदि संभव हो तो विधि का नाम इंगित करना चाहिए कि गणना अनंत है। अर्थात। "IENumerable GetAllPrimeNumbers()" ठीक है, लेकिन मुझे अनफ़ोल्ड जैसे नाम के बारे में निश्चित नहीं है। – Joe

+1

"अनफॉल्ड" उच्च ऑर्डर फ़ंक्शन का नाम है, जो "फोल्ड" के विपरीत है, और आईएमओ, एक सामान्य संदर्भ में एक वैध नाम है। विशिष्ट कार्यान्वयन के लिए, हां, बेहतर नामकरण वांछनीय है। –

+0

बीटीडब्ल्यू, कुल विधि "फोल्ड" फ़ंक्शन का लिंक कार्यान्वयन है, और मेरे ज्ञान के लिए कोई अंतर्निहित उलटा कार्यान्वयन नहीं है। कृपया मुझे सुधारें अगर मैं गलत हूं। –

6

"सामान्यतया बिना यह बुरा desing एक प्रगणक कि रिटर्न आइटम की एक अनंत राशि, प्रदान करना है, की गणना को रोकने के लिए एक तरह से आपूर्ति?"

कोड के उपभोक्ता, कर सकते हैं हमेशा रोक की गणना (उदाहरण के या अन्य साधनों के लिए ब्रेक का उपयोग)। यदि आपका गणक रिटर्न और असीमित अनुक्रम है, इसका मतलब यह नहीं है कि गणनाकर्ता का क्लाइंट किसी भी तरह से गणना को तोड़ने के लिए मजबूर नहीं होता है, वास्तव में आप एक गणक नहीं बना सकते हैं जिसे ग्राहक द्वारा पूरी तरह से समझा जा सकता है।

हम उन प्रकट (...) के बाद लें (...)/TakeWhile (...) बुला पर भरोसा करना चाहिए? (शायद पसंदीदा विकल्प, क्योंकि यह मौजूदा लिंक ज्ञान प्रदान करता है।)

हां, जब तक आप अपने दस्तावेज़ में स्पष्ट रूप से निर्दिष्ट करते हैं कि गणनाकर्ता रिटर्न और अनंत अनुक्रम और गणना का तोड़ने वाला कॉलर की ज़िम्मेदारी है, सबकुछ ठीक होना चाहिए।

असीमित अनुक्रम लौटाना एक बुरा विचार नहीं है, कार्यात्मक प्रोग्रामिंग भाषाओं ने इसे लंबे समय से किया है।

2

मैं जॉन से सहमत हूं। कंपाइलर आपकी विधि को सरल राज्य मशीन को कार्यान्वित करने के लिए कक्षा में बदल देता है जो वर्तमान मूल्य के संदर्भ में रहता है (यानी मूल्य जो वर्तमान संपत्ति के माध्यम से वापस किया जाएगा)। मैंने कोड को सरल बनाने के लिए कई बार इस दृष्टिकोण का उपयोग किया। यदि आप स्पष्ट रूप से विधि के व्यवहार को दस्तावेज करते हैं तो इसे ठीक काम करना चाहिए।

0

मैं सार्वजनिक एपीआई में एक अनंत गणनाकर्ता का उपयोग नहीं करता। सी # प्रोग्रामर, स्वयं शामिल हैं, फोरैच लूप के लिए भी उपयोग किया जाता है। यह .NET Framework के साथ भी सुसंगत होगा; ध्यान दें कि कैसे समेकित। श्रेणी और संख्यात्मक। दोहराना विधियां संख्यात्मक वस्तुओं की संख्या को सीमित करने के लिए एक तर्क लेती हैं। माइक्रोसॉफ्ट ने एन्युमेरेबल के बजाय एन्यूमेरेबल.रिपेट ("", 10) का उपयोग करना चुना। दोहराएं ("))। अनंत गणना से बचने के लिए (10) ले लो। और मैं उनके डिजाइन विकल्पों का पालन करता हूं।

+3

सी # डेवलपर्स को यह सीखना शुरू करना चाहिए कि गणक अनुक्रमों (परिमित या अनंत) पर आधारित हैं और सूचियों से अधिक नहीं। परिमित जेनरेटर समस्याओं के सभी वर्गों के लिए उपयुक्त नहीं हैं, कभी-कभी आप नहीं जानते कि आपको पहले कितने तत्व चाहिए। –

+3

पुनरावृत्ति/रेंज का उद्देश्य दोहराए गए पुनरावृत्तियों के लिए दोहराना है - यही कारण है कि संख्या वहां है। असीमित अनुक्रमों के लिए अन्य परिदृश्यों में यह बिल्कुल उचित है। –

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

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