2011-08-18 11 views
8

मैं डी के लिए एक गतिशील टाइपिंग लाइब्रेरी लागू कर रहा था जब मैं एक रोचक समस्या से भाग गया।डी में गतिशील टाइपिंग का उपयोग करना, एक स्थिर टाइप की गई भाषा

अभी, मैं dynamic() नामक फ़ंक्शन बनाने में सफल रहा हूं जो किसी ऑब्जेक्ट का गतिशील संस्करण देता है।

उदाहरण के लिए:

import std.stdio, std.dynamic.core; 

class Foo 
{ 
    string bar(string a) { return a ~ "OMG"; } 
    int opUnary(string s)() if (s == "-") { return 0; } 
} 

void main(string[] argv) 
{ 
    Dynamic d = dynamic(new Foo()); 
    Dynamic result = d.bar("hi"); 
    writeln(result); // Uh-oh 
} 

समस्या मैं के पार चला गया है तथ्य यह है कि writeln उपयोग करने के लिए संकलन समय प्रतिबिंब यह पता लगाने result के इलाज के लिए कैसे करने के लिए प्रयास करता है।

यह पहली चीज है जो कोशिश करता है? isInputRange!(typeof(result))

समस्या यह है कि यह सच देता है! क्यूं कर? क्योंकि मुझे यह मानना ​​है कि सभी सदस्यों को इसकी आवश्यकता है, जब तक कि मैं रन समय पर अन्यथा साबित नहीं कर सकता - जो बहुत देर हो चुकी है। तो कार्यक्रम front, popFront, और empty पर result पर कॉल करने का प्रयास करता है, जो मेरे प्रोग्राम को दुर्घटनाग्रस्त करता है।

मैं इसे ठीक करने का कोई तरीका नहीं सोच सकता। क्या किसी को कुछ पता है?

उत्तर

1

क्या std.variant जो तुम सब गतिशील टाइपिंग के लिए की जरूरत है

+1

'std.variant' मनमाना क्षेत्रों होने प्रकार का समर्थन नहीं करता। –

+0

@cyber आपका क्या मतलब है? –

+0

ओपी एक ऑब्जेक्ट बनाना चाहता है जहां 'obj.anything' संकलन-समय पर मान्य है (भले ही यह रन-टाइम पर मान्य न हो)। जैसा कि मैंने देखा है, 'std.variant' में कुछ भी ऐसा नहीं करता है। –

1

आप isInputRange के लिए एक अधिभार प्रदान कर सके (वाक्यात्मक चीनी के काफ़ी के साथ) को लागू करता है का उपयोग कर के साथ गलत क्या है? (ध्यान दें कि मैं isInputRange के कार्यान्वयन को देखा नहीं किया है) कुछ इस तरह:

template isInputRange(T : Dynamic) { 
    enum isInputRange = false; 
} 

यह आपके dynamic.core द्वारा प्रदान की जाती है, तो मैं इस अधिभार एसटीडी lib एक पहले से चुना जाना चाहिए लगता है।

+1

सही, लेकिन समस्या यह है कि इसे हर तरह की रोकथाम को पहले से जानने की आवश्यकता होगी। जाहिर है, यह मेरी लाइब्रेरी का उपयोग करने वाले किसी भी व्यक्ति के लिए काम नहीं करता है ... – Mehrdad

+0

दुर्भाग्य से यह चाल काम नहीं करती है, std.stdio विशेषज्ञता नहीं उठा सकता है। – Lutger

0

सामान्य मामले के लिए डायनामिक को संकलन समय पर किसी विधि विधि को स्वीकार करना होगा, जैसा कि आपने कहा था। मान लीजिए कि आप isInputRange को सही करने के लिए अनुमानित करने के लिए अनुमान लगा सकते हैं, अब इनपुट कोड से डायनामिक बनाने का प्रयास करते समय गलत कोड उत्पन्न होगा।

मुझे नहीं लगता कि यह ठीक है, कम से कम सामान्य तरीके से नहीं। इस विशेष मामले में मैं सबसे अच्छा समाधान सोच सकता हूं कि डायनामिक इसे टूस्ट्रिंग का अपना संस्करण प्रदान करता है, और लेखांकन इनपुट रेंज विशेषज्ञता पर पसंद करेंगे। मेरा मानना ​​है कि रीटेल इस समय ऐसा नहीं करता है, कम से कम structs के लिए नहीं, लेकिन शायद यह चाहिए।

एक और समझौता ओपडिस्चैच बाधा में पॉपफ्रंट जैसी कुछ विधियों को अस्वीकार करना होगा, इसके बजाय डायनामिक इन विशेष मामलों तक पहुंचने के लिए opIndex या सदस्य ऑब्जेक्ट प्रदान करेगा। यह उतना बुरा नहीं हो सकता जितना लगता है, क्योंकि विशेष मामले दुर्लभ हैं और उनका उपयोग करने से एक स्पष्ट संकलक त्रुटि होगी।

मुझे लगता है कि गतिशील के लिए इस प्रकार के विधि समाधान को बचाने का सबसे अच्छा तरीका है लेखांकन को ठीक करना और स्वीकार करना कि गतिशील सभी टेम्पलेट कोड के साथ काम नहीं करेगा।

+0

लेख बनाने के साथ परेशानी को स्ट्रिंग करना पसंद है IInputRange यह है कि प्रत्येक वर्ग को ऑब्जेक्ट से जेनेरिक टूस्ट्रिंग विधि प्राप्त होती है, जो क्लास नाम को आउटपुट करता है। इसलिए, यदि रीडेलन बदल दिया गया था, तो इसे अलग-अलग structs और वर्गों का इलाज करना होगा। – tgehr

2

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

कुछ समाधान मैं देख सकता हूँ:

  1. बड़ी मात्रा में प्रयोग कार्यों के लिए अपने स्वयं के गतिशील टाइप किया कार्यान्वयन प्रदान करते हैं। आपके पास जो भी समस्या है, वह इस तथ्य के कारण है कि आप सामान्य कार्यों का उपयोग करने की कोशिश कर रहे हैं जो गतिशील प्रकारों के साथ स्थिर टाइपिंग मानते हैं।

  2. स्पष्ट रूप से चारों ओर गतिशील गतिशील बनाता है, और अंतर्निहित डेटा की स्ट्रिंग में रूपांतरण की देखभाल करता है। (यदि isInputRange समस्या मौजूद नहीं है, तो आपको कस्टम टूस्ट्रिंग विधि को किसी भी तरह से रखना होगा, क्योंकि अन्यथा इसका परिणाम फिर से डायनामिक प्रकार का होगा)। यह शायद लेखेल (डी) बना देगा; काम।

  3. गतिशील के लिए रैपर प्रदान करते हैं जो आपको गतिशील प्रकारों को विभिन्न टेम्पलेट किए गए कार्यों में पारित करने की अनुमति देता है। (वे सिर्फ एक स्थिर इंटरफ़ेस प्रदर्शित करेंगे और गतिशील को सभी कॉल अग्रेषित करेंगे)।

उदाहरण के लिए:

Dynamic d; 
// wrap d to turn it into a compile-time input range (but NOT eg a forward range) 
Dynamic d2=dynamic(map!q{a*2}(dynInputRange(d))); 
// profit 

4। डायनामिक में एक सदस्य टेम्पलेट जोड़ें, जो कुछ सदस्य फ़ंक्शन नामों को स्थैतिक रूप से अक्षम करने की अनुमति देता है।

उदाहरण के लिए:

static assert(!isForwardRange!(typeof(d.without!"save"))); 
संबंधित मुद्दे