कुछ महत्वपूर्ण मुद्दे हैं जो मुझे लगता है कि सभी मौजूदा उत्तर छूट गए हैं।
कमजोर टाइपिंग का मतलब अंतर्निहित प्रतिनिधित्व तक पहुंच की अनुमति देना है। C में, मैं वर्णों के लिए एक पॉइंटर बना सकता हूं, फिर संकलक को बताऊंगा कि मैं इसे पूर्णांक के लिए एक पॉइंटर के रूप में उपयोग करना चाहता हूं:
char sz[] = "abcdefg";
int *i = (int *)sz;
32-बिट पूर्णांकों के साथ एक छोटे से एंडियन प्लेटफॉर्म पर, यह i
संख्याओं की एक सरणी में बनाता है 0x64636261
और 0x00676665
। वास्तव में, आप खुद को पूर्णांक (उपयुक्त आकार के) के लिए संकेत भी दे सकते हैं:
intptr_t i = (intptr_t)&sz;
और निश्चित रूप से इसका मतलब है कि मैं सिस्टम में कहीं भी मेमोरी को ओवरराइट कर सकता हूं। *
char *spam = (char *)0x12345678
spam[0] = 0;
* बेशक आधुनिक OS का वर्चुअल मेमोरी और पेज प्रोटेक्शन का उपयोग करते हैं, इसलिए मैं केवल अपनी प्रक्रिया की मेमोरी को ओवरराइट कर सकता हूं, लेकिन C स्वयं के बारे में ऐसा कुछ भी नहीं है जो इस तरह की सुरक्षा प्रदान करता है, जैसा कि कभी भी जिस पर कोडित किया गया हो, कहे, क्लासिक मैक ओएस या Win16 आपको बता सकता है।
पारंपरिक लिस्प ने हैकरी के समान प्रकार की अनुमति दी; कुछ प्लेटफार्मों पर, डबल-शब्द फ़्लोट्स और कॉन्स सेल एक ही प्रकार के थे, और आप सिर्फ एक फ़ंक्शन को पास कर सकते हैं जो दूसरे की उम्मीद कर रहे हैं और यह "काम" करेगा।
अधिकांश भाषाएं आज सी और लिस्प के रूप में काफी कमजोर नहीं हैं, लेकिन उनमें से कई अभी भी कुछ हद तक टपका हुआ है। उदाहरण के लिए, कोई भी OO भाषा जिसमें "डाउनकास्ट" है, * वह एक प्रकार का रिसाव है: आप अनिवार्य रूप से संकलक को बता रहे हैं "मुझे पता है कि मैंने आपको यह जानने के लिए पर्याप्त जानकारी नहीं दी है कि यह सुरक्षित है, लेकिन मुझे पूरा यकीन है यह है, "जब एक प्रकार की प्रणाली का पूरा बिंदु यह है कि संकलक के पास हमेशा यह जानने के लिए पर्याप्त जानकारी होती है कि क्या सुरक्षित है।
* एक चेक डाउनकास्ट भाषा के प्रकार प्रणाली को किसी भी कमजोर नहीं बनाता है क्योंकि यह चेक को रनटाइम में ले जाता है। यदि यह किया है, तो उप-प्रकार बहुरूपता (उर्फ आभासी या पूरी तरह से गतिशील फ़ंक्शन कॉल) टाइप सिस्टम का एक ही उल्लंघन होगा, और मुझे नहीं लगता कि कोई भी ऐसा कहना चाहता है।
बहुत कम "स्क्रिप्टिंग" भाषाएं इस अर्थ में कमजोर हैं। Perl या Tcl में भी, आप एक स्ट्रिंग नहीं ले सकते हैं और सिर्फ इसके बाइट्स को एक पूर्णांक के रूप में व्याख्या कर सकते हैं। * लेकिन यह ध्यान देने योग्य है कि CPython में (और इसी तरह कई भाषाओं के लिए कई अन्य दुभाषियों के लिए), यदि आप वास्तव में लगातार हैं, तो आप ctypes
लोड करने के लिए उपयोग कर सकते हैं libpython
, एक वस्तु id
को एक में डाल सकते हैं POINTER(Py_Object)
, और प्रकार प्रणाली को लीक करने के लिए मजबूर कर सकते हैं। क्या यह प्रकार प्रणाली को कमजोर बनाता है या नहीं, आपके उपयोग के मामलों पर निर्भर करता है - यदि आप सुरक्षा सुनिश्चित करने के लिए इन-लैंग्वेज प्रतिबंधित निष्पादन सैंडबॉक्स लागू करने का प्रयास कर रहे हैं, तो आपको इस प्रकार के पलायन से निपटना होगा ...
* आप struct.unpack
बाइट्स पढ़ने के लिए एक फ़ंक्शन का उपयोग कर सकते हैं और "सी कैसे इन बाइट्स का प्रतिनिधित्व करेंगे" से एक नया इंट का निर्माण करते हैं, लेकिन यह स्पष्ट रूप से लीक नहीं है; यहां तक कि हास्केल अनुमति देता है।
इस बीच, अंतर्निहित रूपांतरण वास्तव में एक कमजोर या टपका हुआ प्रकार की प्रणाली से एक अलग बात है।
हर भाषा, यहां तक कि हास्केल, के पास एक पूर्णांक को एक स्ट्रिंग या फ्लोट में बदलने, कहने, कार्य करने के लिए है। लेकिन कुछ भाषाएं आपके लिए उन रूपांतरणों में से कुछ स्वचालित रूप से करेंगी - जैसे, C में, यदि आप एक फ़ंक्शन को कॉल करते हैं जो एक चाहता है float
, और आप इसे पास करते हैं int
, तो यह आपके लिए परिवर्तित हो जाता है। इससे निश्चित रूप से, बग़ल में, अप्रत्याशित ओवरफ्लो के साथ कीड़े पैदा हो सकते हैं, लेकिन वे एक ही प्रकार के कीड़े नहीं हैं जो आपको कमजोर प्रकार की प्रणाली से मिलते हैं। और सी वास्तव में यहाँ कोई कमजोर नहीं है; आप हास्केल में एक इंट और फ्लोट जोड़ सकते हैं, या यहां तक कि एक स्ट्रिंग के लिए एक फ्लोट को जोड़ सकते हैं, आपको बस इसे और अधिक स्पष्ट रूप से करना होगा।
और गतिशील भाषाओं के साथ, यह बहुत आसान है। पायथन या पर्ल में "एक फ़ंक्शन जो फ्लोट चाहता है" जैसी कोई चीज नहीं है। लेकिन अतिभारित कार्य हैं जो विभिन्न प्रकारों के साथ अलग-अलग काम करते हैं, और एक मजबूत सहज ज्ञान युक्त भावना है, उदाहरण के लिए, एक स्ट्रिंग को कुछ और से जोड़ना "एक फ़ंक्शन है जो एक स्ट्रिंग चाहता है"। उस अर्थ में, पर्ल, Tcl, और जावास्क्रिप्ट बहुत सारे निहितार्थ रूपांतरण ( "a" + 1
आपको देता है "a1"
) करते हुए दिखाई देते हैं , जबकि पायथन बहुत कम करता है ( "a" + 1
एक अपवाद को उठाता है, लेकिन 1.0 + 1
आपको 2.0
* देता है)। यह केवल औपचारिक शब्दों में रखना कठिन है - ऐसा क्यों नहीं होना चाहिए +
जो एक स्ट्रिंग और एक इंट लेता है, जब स्पष्ट रूप से अन्य फ़ंक्शन होते हैं, जैसे कि अनुक्रमण, जो करते हैं?
* दरअसल, आधुनिक पायथन में, जिसे OO सबटाइपिंग के संदर्भ में समझाया जा सकता है, क्योंकि isinstance(2, numbers.Real)
यह सच है। मुझे नहीं लगता कि 2
पर्ल या जावास्क्रिप्ट में स्ट्रिंग प्रकार का कोई उदाहरण है ... हालांकि Tcl में, यह वास्तव में है, क्योंकि सब कुछ स्ट्रिंग का एक उदाहरण है।
अंत में, एक और, पूरी तरह से ऑर्थोगोनल है, "मजबूत" बनाम "कमजोर" टाइपिंग की परिभाषा, जहां "मजबूत" का अर्थ है शक्तिशाली / लचीला / अभिव्यंजक।
उदाहरण के लिए, हास्केल आपको एक प्रकार परिभाषित करता है जो एक संख्या, एक स्ट्रिंग, इस प्रकार की एक सूची, या इस प्रकार के तार से एक नक्शा है, जो कि JSON से डिकोड किए जा सकने वाली किसी भी चीज़ का प्रतिनिधित्व करने के लिए एक पूरी तरह से तरीका है। जावा में इस प्रकार को परिभाषित करने का कोई तरीका नहीं है। लेकिन कम से कम जावा में पैरामीट्रिक (जेनेरिक) प्रकार होते हैं, इसलिए आप एक फ़ंक्शन लिख सकते हैं जो T की सूची लेता है और यह जानता है कि तत्व टाइप T के हैं; अन्य भाषाओं, जैसे शुरुआती जावा, ने आपको ऑब्जेक्ट की सूची और डाउनकास्ट का उपयोग करने के लिए मजबूर किया। लेकिन कम से कम जावा आपको अपने स्वयं के तरीकों के साथ नए प्रकार बनाने देता है; C केवल आपको संरचनाएँ बनाने देता है। और BCPL के पास भी ऐसा नहीं था। और इसलिए नीचे विधानसभा में, जहां केवल प्रकार अलग-अलग बिट लंबाई हैं।
तो, उस अर्थ में, हास्केल का प्रकार प्रणाली आधुनिक जावा की तुलना में अधिक मजबूत है, जो कि पहले के जावा की तुलना में अधिक मजबूत है, जो सी की तुलना में अधिक मजबूत है, जो बीसीपीएल से अधिक मजबूत है।
तो, पायथन उस स्पेक्ट्रम में कहां फिट बैठता है? यह थोड़ा मुश्किल है। कई मामलों में, बतख टाइपिंग आपको उन सभी चीजों को अनुकरण करने की अनुमति देता है जो आप हास्केल में कर सकते हैं, और यहां तक कि कुछ चीजें जो आप नहीं कर सकते हैं; यकीन है, संकलन समय के बजाय त्रुटियों को रनटाइम पर पकड़ा जाता है, लेकिन वे अभी भी पकड़े गए हैं। हालांकि, ऐसे मामले हैं जहां बतख टाइपिंग पर्याप्त नहीं है। उदाहरण के लिए, हास्केल में, आप बता सकते हैं कि किलों की एक खाली सूची, किलों की एक सूची है, इसलिए आप यह तय कर सकते हैं कि +
उस सूची को कम करके 0 * वापस करना चाहिए; पायथन में, एक खाली सूची एक खाली सूची है; आपको यह तय करने में मदद करने के लिए कोई प्रकार की जानकारी नहीं है कि +
इसे क्या करना चाहिए।
* वास्तव में, हास्केल आपको ऐसा करने नहीं देता है; यदि आप कम फ़ंक्शन को कहते हैं जो एक खाली सूची पर प्रारंभ मूल्य नहीं लेता है, तो आपको एक त्रुटि मिलती है। लेकिन इसका प्रकार प्रणाली काफी शक्तिशाली है कि आप यह काम कर सकते हैं, और पायथन का नहीं है।