2010-10-15 8 views
5

मैं ओकैमल में एक अपवाद को परिभाषित करने की कोशिश कर रहा हूं जो सूचियों की एक ट्यूपल जोड़ी को तर्क के रूप में स्वीकार करता है। हालांकि, यह स्थिति काम नहीं करती है?तर्क के रूप में tuple के साथ अपवादों को परिभाषित करना

# exception Foo of string list * string list;; 
exception Foo of string list * string list 
# let bar = (["a"], ["b"; "c"; "d"]);; 
val bar : string list * string list = (["a"], ["b"; "c"; "d"]) 
# raise(Foo bar);; 
Error: The constructor Foo expects 2 argument(s), 
     but is applied here to 1 argument(s) 

हालांकि, अगर मैं ऐसा करते हैं, यह

# raise (Foo (["a"], ["b"; "c"; "d"]));; 
Exception: Foo (["a"], ["b"; "c"; "d"]). 

सौदा क्या है काम करता है? धन्यवाद!

उत्तर

11

आप यह गलत देख रहे हैं (हालांकि मैं आपको दोष नहीं दूंगा: यह पहली बार आश्चर्यजनक है)। ऐसा प्रतीत होता है कि निर्माता सिंटैक्स Name of type का पालन करते हैं जहां टाइप भाग सामान्य प्रकार सिंटैक्स का अनुसरण करता है (जो इसमें टुपल्स को शामिल करता है)।

हकीकत में, tuples और कंस्ट्रक्टर ठीक उसी वाक्य रचना का पालन करें: एक निर्माता केवल इसे के सामने एक नाम के साथ एक टपल है:

tuple/constructor == [name of] type [* type] [* type] ... 

तो, एक निर्माता परिभाषा * का हिस्सा नहीं हैं ट्यूपल सिंटैक्स, वे कन्स्ट्रक्टर सिंटैक्स का हिस्सा हैं। आप के रूप में इस नाम को के रूप में इस नाम के बाद सचमुच एक कन्स्ट्रक्टर को परिभाषित कर रहे हैं, इसके बाद एक तर्क है जिसके बाद एक तर्क है।

व्यवहार में इस सूक्ष्म अंतर के पीछे कारण प्रदर्शन में से एक है। अभी, tuples और निर्माताओं जैसे स्मृति में प्रतिनिधित्व कर रहे हैं:

[TYPE] [POINTER] [POINTER] [POINTER] 

यह एक काफी कॉम्पैक्ट और कुशल प्रतिनिधित्व है।यदि किसी कन्स्ट्रक्टर के कई तर्कों को वास्तव में टुपल के रूप में एक्सेस किया जा सकता है, तो इसे रनटाइम को उस कन्स्ट्रक्टर से स्वतंत्र रूप से टुपल का प्रतिनिधित्व करने की आवश्यकता होगी (इसे स्वतंत्र रूप से संबोधित करने के लिए) और इसलिए यह इस तरह दिखेगा:

[TYPE] [POINTER] 
      | 
      v 
      [TYPE] [POINTER] [POINTER] [POINTER] 

यह मामूली अधिक स्मृति का प्रयोग करेंगे, जब एक निर्माता का उपयोग कर दो बार के रूप में कई आवंटन की आवश्यकता होती है, और (एक अतिरिक्त भिन्नता की वजह से) पैटर्न मिलान tuples के प्रदर्शन को कम। आदेश अधिकतम प्रदर्शन को बनाए रखने के लिए, name of type * type पहले पद्धति का उपयोग कर प्रस्तुत किया जाता है, और आप स्पष्ट रूप से टाइप करने के लिए name of (type * type)of से * काट और इस तरह दूसरी तर्ज पर वापस गिर करने की जरूरत है।

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

प्रकार here की स्मृति प्रतिनिधित्व पर अतिरिक्त पढ़ने।

+0

वाह चाहता हूं! लंबी व्याख्या के लिए धन्यवाद! ओकैमल की आपकी समझ ऐसा लगता है कि आप INRIA से हैं – axsuul

4

Foo 2 पैरामीटर के साथ अपवाद का एक निर्माता है। आपको ट्यूपल को विघटित करना होगा और इसमें प्रत्येक भाग को पार करना होगा।

# exception Foo of string list * string list;; 
exception Foo of string list * string list 
# let bar = (["a"], ["b"; "c"; "d"]);; 
val bar : string list * string list = (["a"], ["b"; "c"; "d"]) 
# let a, b = bar in raise (Foo (a, b));; 
Exception: Foo (["a"], ["b"; "c"; "d"]). 

आप एकल पैरामीटर के रूप में एक टपल का उपयोग करना चाहते हैं, तो आप कोष्ठक का उपयोग कर अपवाद को परिभाषित करने और में टपल गुजरना होगा।

# exception Foo of (string list * string list);; 
exception Foo of (string list * string list) 
# let bar = (["a"], ["b"; "c"; "d"]);; 
val bar : string list * string list = (["a"], ["b"; "c"; "d"]) 
# raise (Foo bar);; 
Exception: Foo (["a"], ["b"; "c"; "d"]). 
+0

धन्यवाद :) यह काम करता है कि मैं कैसे – axsuul

5

इस संबंध में, OCaml के अपवाद कंस्ट्रक्टर्स सिर्फ साधारण की तरह हैं रचनाकार:

Constr(1,2,3) एक विशेष वाक्य रचनात्मक निर्माण है जिसमें कोई ट्रिपल नहीं होता है। दूसरी ओर, Constr((1,2,3)) में एक तिहाई होता है। कार्यान्वयन इस व्यवहार से मेल खाता है, Constr(1,2,3) को एक ही ब्लॉक के रूप में आवंटित किया जा रहा है, और Constr((1,2,3)) दो ब्लॉक के रूप में, जिसमें एक दूसरे के लिए एक सूचक (ट्रिपल) होता है। Constr(1,2,3) के रन-टाइम प्रतिनिधित्व में पॉइंटर प्राप्त करने के लिए कोई तिगुना नहीं है, और यदि आपको किसी की आवश्यकता है तो आपको एक नया आवंटन करना होगा।

नोट: Constr(((1,2,3)))Constr((1,2,3)) के बराबर है। Constr(((1,2,3))) में, मध्य कोष्ठक को (1,2,3) अभिव्यक्ति के चारों ओर जाने के रूप में व्याख्या किया जाता है, और एक अभिव्यक्ति के चारों ओर कोष्ठक सार वाक्यविन्यास पेड़ में भुला दिया जाता है।

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