अब तक सिलेबस ने टाइप के बारे में ज़्यादा कुछ नहीं कहा है, लेकिन साफ है कि Julia में ये मौजूद हैं:
julia> vals = (42, 4.3, π, "hello", 'Q')
(42, 4.3, π, "hello", 'Q')
julia> typeof(vals)
Tuple{Int64, Float64, Irrational{:π}, String, Char}
हमने टाइप कभी निर्दिष्ट नहीं किए, फिर भी Julia ने उन्हें असाइन कर दिया।
types हैं, जो इसके डिज़ाइन के केंद्र में हैं।Type Inference का उपयोग करके टाइप का "अनुमान" लगा सकती है।JIT कंपाइलर (सारे) कोड को देखता है, यह देखता है कि किसी वेरिएबल का उपयोग कैसे हो रहा है, और उस उपयोग के अनुरूप एक उपयुक्त डिफॉल्ट टाइप का अनुमान लगाता है।
आसान ट्यूटोरियल अभ्यास हल करने के लिए टाइप इनफेरेंस पर भरोसा करना ठीक है, लेकिन बड़े प्रोग्राम के लिए आपको ज़्यादा सटीक नियंत्रण की ज़रूरत पड़ सकती है।
ज़्यादातर आधुनिक प्रोसेसर पर एक पूर्णांक का डिफॉल्ट Int64 होता है।
हमने Numbers कॉन्सेप्ट में देखा था कि किसी वैल्यू को किसी खास गैर-डिफॉल्ट टाइप में बदला जा सकता है।
julia> x = Int16(42)
42
julia> typeof(x)
Int16
लेकिन वेरिएबल x को किसी दूसरे टाइप की वैल्यू फिर भी असाइन की जा सकती है:
julia> x = "changed"
"changed"
julia> typeof(x)
String
यह type instability है, और इसका मतलब है:
इसके बजाय, हम :: ऑपरेटर का उपयोग करके x का टाइप तय कर सकते हैं:
julia> y::Int16 = 42
42
julia> typeof(y)
Int16
julia> y = "changed"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int16
The function `convert` exists, but no method is defined for this combination of argument types.
अब y का टाइप Int16 है, और हमेशा रहेगा।
इसलिए कंपाइलर को पता होता है कि इसके लिए कितने बाइट आरक्षित करने हैं, और वह बाकी कोड को इस तरह ऑप्टिमाइज़ कर सकता है कि वह एक स्थिर टाइप पर भरोसा करे।
इस मायने में यह वेरिएबल C जैसी स्टैटिकली-टाइप्ड भाषा के वेरिएबलो जैसा ही है।
Int64, Int16, String, Char: ये टाइप "कहाँ से आते हैं"?
कई ऑब्जेक्ट-ओरिएंटेड (OO) भाषाओं में हर टाइप एक क्लास होता है, सबक्लासिंग उन्हें एक क्लास पदानुक्रम में सजाती है, और क्लास मेथड उनका व्यवहार तय करते हैं।
Java और Ruby इस पैटर्न के साफ उदाहरण हैं, लेकिन अंदरूनी रूप से Python भी ऐसी ही है।
Julia में क्लास नहीं होती।
दस्तावेज़ों में दिया गया कारण यह है कि OO फीचर JIT कंपाइलर में रुकावट डालते हैं और रनटाइम परफ़ॉर्मेंस को नुकसान पहुँचाते हैं।
फिर भी, इस कोड को देखिए:
julia> y::Int16 = 42
42
julia> typeof(y)
Int16
julia> supertype(Int16)
Signed
julia> supertypes(Int16)
(Int16, Signed, Integer, Real, Number, Any)
कुछ बातें स्पष्ट कर लेते हैं:
Int16 एक टाइप है, और हम इस टाइप के वेरिएबल बना सकते हैं।Int16, Signed का सबटाइप है, और supertype() फंक्शन हमें यह दिखाता है।Integer, Real और Number से होते हुए सबसे ऊपर Any तक जाता है, और subtypes() हमें पदानुक्रम की यह शाखा दिखा देगा।सारी शाखाएँ Any पर जाकर खत्म होती हैं, और Any इस मायने में अनोखा है कि वह खुद अपना ही सुपरटाइप है।
julia> supertypes(String)
(String, AbstractString, Any)
julia> supertype(Any)
Any
तो Julia में class का पदानुक्रम नहीं है, लेकिन type का पदानुक्रम ज़रूर है।
आगे चलकर हम यह समझने की कोशिश करेंगे कि यह काम कैसे करता है, लेकिन पहले अभी बहुत कुछ खोजना बाकी है।
हम सामान्य तरीके से बराबरी की जाँच के लिए typeof() का उपयोग कर सकते हैं।
julia> typeof(11)
Int64
julia> typeof(11) == Int64
true
julia> typeof(11) == Number
false
टाइप की बराबरी बिल्कुल सटीक होनी चाहिए, क्योंकि तुलना के इस तरीके को टाइप पदानुक्रम की कोई समझ नहीं होती।
इससे ज़्यादा लचीले ढंग से, isa हमें बताता है कि किसी वैल्यू का टाइप तुलना करने वाले टाइप जैसा ही है या उसका कोई सबटाइप है।
इसका उपयोग फंक्शन रूप में या इनफ़िक्स रूप में, दोनों तरह से किया जा सकता है।
julia> 12 isa Int64
true
julia> 12 isa Number
true
julia> isa(12, Number)
true
julia> 12 isa String
false
ध्यान दीजिए कि isa बाईं ओर एक value की अपेक्षा करता है, type की नहीं।
इस तरह दो टाइपो की तुलना करने पर अनपेक्षित परिणाम मिलेंगे।
सही ऑपरेटर <: है, जिसे हम आगे के कॉन्सेप्ट में और भी बहुत बार देखेंगे।
julia> Int64 isa Number ## Don't do this!
false
julia> Int64 <: Number
true
हमने देखा कि टाइप पदानुक्रम एक पेड़ जैसी संरचना बनाता है (CS के अर्थ में, जिसकी जड़ सबसे ऊपर होती है)।
पेड़ में हर चीज़ एक node होती है, और इन्हें वर्गों में बाँटा जा सकता है:
node के सबटाइप होते हैं, उन्हें abstract कहा जाता है।node को concrete कहा जाता है।julia> subtypes(Integer) # an abstract type
3-element Vector{Any}:
Bool
Signed
Unsigned
julia> subtypes(Int64) # a concrete type
Type[]
यह एक महत्वपूर्ण अंतर है, क्योंकि सिर्फ कॉन्क्रीट टाइप को ही वेरिएबल के रूप में instantiated किया जा सकता है।
julia> a::Int16 = 42
42
julia> typeof(a)
Int16
julia> b::Integer = 42
42
julia> typeof(b)
Int64
ध्यान दीजिए कि एब्स्ट्रैक्ट टाइप इस्तेमाल करने पर (इस मामले में) कोई एरर संदेश नहीं मिलता, लेकिन कंपाइलर एक उपयुक्त कॉन्क्रीट टाइप बना देता है: Integer की जगह Int64।
इस अभ्यास में आप ग्रेडिंग डेटा को प्रीप्रोसेस करके थोड़ी डेटा इंजीनियरिंग करेंगे। एक स्कूल में बहुत, बहुत, बहुत (बहुत ज़्यादा?) विद्यार्थी हैं, और वह विद्यार्थियों को मिले अंकों का डेटा विश्लेषण करना चाहता है। वह यह काम कुशलता से करना चाहता है, इसलिए सोच यह है कि डेटा को कम से कम किया जाए और व्यवस्थित किया जाए।
ग्रेडिंग स्केल आम तौर पर 0-10 तक होता है, इसलिए हर ग्रेड के लिए केवल आठ बिट वाला डेटा टाइप इस्तेमाल करना सबसे कुशल है।
UInt8 डेटा टाइप में बदलना होगा।Int8 डेटा टाइप में बदलना होगा।अंकों को बदलने वाला फंक्शन बनाने के बाद आपको एक और फंक्शन लिखना होगा, जो उन संग्रहों को संभालेगा जिनमें अंक रखे गए हैं। यह फंक्शन अंकों को डिमोट करेगा और उन्हें अवरोही क्रम में लौटाएगा।
Vector में रखते हैं, क्योंकि वे अपने डेटा के बारे में बहुत चौकस रहते हैं।Set में रखते हैं, जो क्रमबद्ध नहीं होते, क्योंकि वे थोड़े आलसी हैं।दोनों फंक्शनों में अमान्य इनपुट मिलने पर आपको एक MethodError फेंकना होगा।
एक्सेप्शन हैंडलिंग को आगे के किसी कॉन्सेप्ट में समझाया जाएगा, इसलिए इस अभ्यास के लिए आप नीचे दिया गया सिंटैक्स इस्तेमाल कर सकते हैं:
throw(MethodError(f, args))
यहाँ f फंक्शन है और args उन आर्गुमेंट का टपल है जो फंक्शन को दिए जाते हैं।
demote(n) फंक्शन में f यानी demote है और args यानी (n,) है:
throw(MethodError(demote, (n,)))
demote(n) मेथड बनाइए।
Float64 इनपुट मिलने पर यह निकटतम पूर्ण संख्या तक ऊपर की ओर राउंड करे और UInt8 डेटा टाइप लौटाए।Integer के साथ यह उसी पूर्णांक को Int8 डेटा टाइप में लौटाए।julia> demote(4.2)::UInt8
5
julia> demote(4)::Int8
4
julia> demote("hi")
MethodError: no method matching demote(::String) #output truncated
preprocess(coll) मेथड बनाइए।
Vector इनपुट मिलने पर यह सभी संख्याओं को डिमोट करे और वेक्टर को उलट दे।Set इनपुट मिलने पर यह सभी संख्याओं को डिमोट करे और अवरोही क्रम में क्रमबद्ध वेक्टर लौटाए।julia> preprocess([1, 2, 3])
3-element Vector{Int8}:
3
2
1
julia> preprocess(Set([2.2, 5.8, 3.4]))
3-element Vector{UInt8}:
6
4
3
julia> preprocess(42)
MethodError: no method matching preprocess(::Int64) #output truncated
Exercism पर साइन अप कीजिए और Julia को 35 कॉन्सेप्ट128 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।