2012-05-02 12 views
11

यह व्यवहार क्यों होता है?ओकैम Printf.sprintf

# Printf.sprintf ("Foo %d %s") 2 "bar";; 
- : string = "Foo 2 bar" 

# Printf.sprintf ("Foo %d"^" %s") 2 "bar";; 
    Printf.sprintf ("Foo %d"^" %s") 2 "bar";; 
Error: This expression has type string but an expression was expected of type 
     ('a -> 'b -> 'c, unit, string) format = 
      ('a -> 'b -> 'c, unit, string, string, string, string) format6 

मैं उम्मीद होती है कि स्ट्रिंग संयोजन पहले मूल्यांकन किया जाना होगा, तो सब कुछ के रूप में सामान्य आगे बढ़ेंगे। क्या इसे टाइप सिस्टम ट्रिकरी के साथ करना है जो प्रिंटफ नियोजित करता है?

उत्तर

17

हां, इसे टाइप सिस्टम ट्रिकरी के साथ करना है। यदि आप एक प्रारूप स्ट्रिंग बनाना चाहते हैं आप (^^) ऑपरेटर का उपयोग करने की आवश्यकता है:

# Printf.sprintf ("Foo %d" ^^ " %s") 2 "bar";; 
- : string = "Foo 2 bar" 

मैं गहराई से इस प्रवंचना में स्कूली नहीं हूँ, लेकिन मुझे विश्वास है कि संकलक एक स्ट्रिंग लगातार बढ़ावा देने के लिए तैयार है यदि टाइपिंग संदर्भ इसके लिए कॉल करता है तो प्रिंटफ़ प्रारूप में। हालांकि, ("Foo %d"^" %s") का परिणाम स्ट्रिंग स्थिर नहीं है, इसलिए इसे प्रचारित नहीं किया जाता है। (^^) ऑपरेटर एक टाइपिंग संदर्भ बनाता है जहां स्ट्रिंग स्थिरांक होने पर दोनों ऑपरेटरों को प्रचारित किया जा सकता है।

आप देख सकते हैं कि इसे एक स्ट्रिंग स्थिर क्यों होना चाहिए: अन्यथा संबंधित प्रकार (मुद्रित होने वाले मानों का) निर्धारित नहीं किया जा सकता है।

+1

एक बढ़िया स्पष्टीकरण, धन्यवाद। एक मामूली बात, मुझे आपका फॉर्मूलेशन मिल गया है "(^^) ऑपरेटर एक टाइपिंग संदर्भ बनाता है .." अस्पष्ट; इस ऑपरेटर के अंदर कोई जादू नहीं है, यह सिर्फ टाइप किया गया है ... प्रारूप -> ... प्रारूप -> ... प्रारूप', और टाइप अनुमान यह जांचने का काम करता है कि इसके पैरामीटर इस प्रकार के हैं, निरंतर तार। – gasche

+1

गैसचे सही है। क्या समझने की आवश्यकता है कि जब आप 'प्रिंट' * printf' को स्ट्रिंग देते हैं तो आप इसे 'Pervasives.string' प्रकार का मान नहीं देते हैं, तो आप इसे' Pervasives.format6' '(जो नहीं है) का मान देते हैं 'Pervasives.string' के बराबर)। –

+0

ठीक है, मुझे अभी यह कहना चाहिए था कि (^^) में प्रकार गैसचे देता है। उस हिस्से में निश्चित रूप से कोई जादू नहीं है। एकमात्र जादू (जैसा कि मैं इसे समझता हूं) उपयुक्त 'प्रारूप' प्रकार के लिए स्ट्रिंग स्थिरांक के प्रचार में है। –

8

समस्या ^ ऑपरेटर के मुकाबले कहीं अधिक व्यापक रूप से होती है। असल में, ओकैमल कंपाइलर को यह पता होना चाहिए कि आपकी प्रारूप स्ट्रिंग एक शाब्दिक स्ट्रिंग है, और शाब्दिक स्ट्रिंग को संकलन समय पर जाना जाना चाहिए। अन्यथा, OCaml संकलन समय पर आपकी स्ट्रिंग को BLAHBLAH format6 प्रकार पर नहीं डाला जा सकता है। Printf मॉड्यूल केवल प्रारूप स्ट्रिंग्स के साथ सही ढंग से काम करता है जो संकलित समय पर पूरी तरह से ज्ञात हैं, या स्वरूप स्ट्रिंग्स के साथ जो पहले ही BLAHBLAH format प्रकार पर डाले गए हैं।

आम तौर पर आप ^^ ऑपरेटर का उपयोग करके और स्पष्ट रूप से अपने कोड में उन लोगों के तार का उपयोग कर से पहले BLAHBLAH format प्रकार करने के लिए सभी शाब्दिक तार कास्टिंग द्वारा इस समस्या का समाधान कर सकते हैं।

# Printf.sprintf (if true then "%d" else "%d ") 2;; 
    Error: This expression has type string but an expression was expected of type 
    ('a -> 'b, unit, string) format = 
     ('a -> 'b, unit, string, string, string, string) format6 
    (* define a type abbreviation for brevity *) 
    # type ('a,'b) fformat = ('a ->'b, unit, string) format;; 
    type ('a, 'b) fformat = ('a -> 'b, unit, string) format 
    # Printf.sprintf (if true then ("%d":('a,'b)fformat) else ("%d ":('a,'b)fformat)) 2;; 
    - : string = "2" 

OCaml प्रणाली पहचान नहीं कर सकते कि if ... then "a" else "b"BLAHBLAH format लिए डाली जा सकता है:

यहाँ एक और उदाहरण है। यदि आपने प्रत्येक शाब्दिक स्ट्रिंग को BLAHBLAH format पर डाला है, तो सब कुछ काम करता है। (नोट: यदि आप, BLAHBLAH format करने के लिए पूरे if/then/else कास्ट करने के लिए के बाद से OCaml सत्यापित नहीं कर सकता है कि आपके स्ट्रिंग एक शाब्दिक है की कोशिश यह काम नहीं करता।)

समस्या के मूल प्रकार सुरक्षा की आवश्यकता है: OCaml कि आवश्यकता है वहाँ प्रत्येक %d और %s इत्यादि के लिए सही प्रकार का तर्क है, और संकलन समय पर इसकी गारंटी देता है। आप Printf के साथ टाइप सुरक्षा की गारंटी नहीं दे सकते हैं जब तक कि संपूर्ण प्रारूप स्ट्रिंग संकलित समय पर ज्ञात न हो। इसलिए, एक जटिल एल्गोरिदम के माध्यम से गणना की गई प्रारूप स्ट्रिंग के साथ Printf का उपयोग करना असंभव है, उदाहरण के लिए, यादृच्छिक रूप से %s और %d चुनकर।

जब हम प्रारूप स्ट्रिंग की गणना करने के लिए if/then/else का उपयोग करते हैं, तो ओकैम चीजें, ओह जी, यह एक जटिल एल्गोरिदम है, और यह संकलन समय पर प्रकार की सुरक्षा को सत्यापित करने के लिए निराशाजनक है। ^^ ऑपरेटर BLAHBLAH format प्रकारों के बारे में जानता है और प्रारूप स्ट्रिंग को संयोजित करते समय सही परिणाम उत्पन्न करता है।लेकिन if/then/else को BLAHBLAH format के बारे में पता नहीं है, और if/then/else पर कोई अंतर्निहित विकल्प नहीं है (लेकिन मुझे लगता है कि आप स्वयं ऐसी चीज को परिभाषित कर सकते हैं)।

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

  • कोई संबंधित समस्या नहीं^_^