2010-07-27 10 views
7

में लागू संकेतों को टाइप न करें मैंने फ़ील्ड के लिए प्रकार संकेतों के साथ defrecord का उपयोग करके एक प्रकार बनाया है। हालांकि, मैंने पाया कि इन प्रकार के संकेत रचनाकारों में लागू नहीं होते हैं और मैं उनके साथ कुछ अजीब चीजें करने में सक्षम हूं। उदाहरण के लिए नीचे दिए गए स्निपेट को देखो:डिफ्रेकॉर्ड कन्स्ट्रक्टर

user=> (defrecord Person [#^String name #^Integer age]) 
user.Person 
user=> (seq (.getConstructors Person)) 
(#<Constructor public user.Person(java.lang.Object,java.lang.Object, 
java.lang.Object,java.lang.Object)> 
#<Constructor public user.Person(java.lang.Object,java.lang.Object)>) 
user=> (Person. (Integer. 123) "abhinav") 
#:user.Person{:name 123, :age "abhinav"} 

निर्माता दिखाया प्रदान की प्रकार संकेत के साथ मेल नहीं खाते हस्ताक्षर (वे String और Integer दोनों के लिए Object का उपयोग करें) और मैं गलत क्षेत्र प्रकार के साथ वस्तुओं का निर्माण करने में सक्षम हूँ।

क्या मेरे कोड में कुछ गड़बड़ है या क्या यह क्लोजर में एक बग है?

मैं क्लोजर 1.2.0-बीटा 1 पर हूं।

+3

एक तरफ, यदि आपका कोड 1.2 विशेषताओं पर निर्भर करता है, तो आपको पाठक मेटाडेटा को शुरू करने के लिए '^' ''^^ 'को प्राथमिकता देना चाहिए; '# ^' का पुराना अर्थ 1.2 में बहिष्कृत है। –

उत्तर

8

प्रतिबिंब से बचने के लिए टाइप-संकेत का उपयोग किया जाता है; वे (वर्तमान में) फ़ंक्शन या कन्स्ट्रक्टर तर्कों को स्थिर रूप से टाइप नहीं करते हैं (अपवाद प्राइमेटिव है क्योंकि उन्हें Object के तहत कम नहीं किया जा सकता है)। इस प्रकार, वे एक सरल रिकार्ड के लिए ज्यादा कुछ नहीं है, लेकिन उन्होंने इस मामले करते हैं जब इसे जोड़ने प्रोटोकॉल कार्यान्वयन के लिए आता है, जैसे:

 
user=> (set! *warn-on-reflection* true) 
true 
user=> (defprotocol P (foo [p])) 
P 
user=> (defrecord R [s] P (foo [_] (.getBytes s))) ; getBytes is a method on String 
Reflection warning, NO_SOURCE_PATH:6 - reference to field getBytes can't be resolved. 
user.R 
user=> (foo (R. 5)) 
java.lang.IllegalArgumentException: No matching field found: getBytes for class java.lang.Integer (NO_SOURCE_FILE:0) 
user=> (defrecord R [^String s] P (foo [_] (.getBytes s))) 
user.R 
user=> (foo (R. 5)) 
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0) 

दो संस्करणों के बीच अंतर यह है कि बाद के बाईटकोड String.getBytecode() बुला उत्सर्जन करता है (इसलिए क्लासकास्ट एक्सेप्शन जब एक इंटीजर पास करता है), जबकि पूर्व को देखने की जरूरत है कि वास्तव में .getBytes का मतलब है कि फ़ंक्शन में पारित रनटाइम ऑब्जेक्ट के संबंध में (और यह प्रक्रिया एक इंटीजर पारित होने पर विफल हो जाती है)।

5

जहां तक ​​मेरा बता सकते हैं, deftype और defprotocol खेतों पर प्रकार संकेत वर्तमान में केवल जब एक आदिम प्रकार शामिल है लागू करने के तरीके:

(deftype Foo [^int x]) 

(Foo. 5) ; => OK 
(Foo. :foo) ; => no go 

;; ... and likewise with defprotocol 

मैं, यह एक मान्यता प्राप्त मुद्दा होने का एक बहुत अस्पष्ट याद है, हालांकि मुझे यकीन नहीं है कि योजना इस व्यवहार को दस्तावेज करने या गैर-आदिम संकेतों को लागू करने के लिए है ... मैं पता लगाने की कोशिश करूंगा।

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