सिलेबस में इस जगह तक पहुँचते-पहुँचते आप फंक्शन की बहुत सी परिभाषाएँ देख चुके हैं। आम तौर पर इन्हें REPL के आउटपुट के बारे में ज़्यादा कुछ बताए बिना ही पेश किया गया था:
julia> f(x) = x^2
f (generic function with 1 method)
तो यह "generic function with 1 method" क्यों लिखा आता है?
मान लीजिए हम आर्गुमेंट के टाइप के बारे में और स्पष्ट होना चाहते हैं।
julia> f(x::Integer) = x^2
f (generic function with 2 methods)
julia> f(x::Real) = x^2
f (generic function with 3 methods)
या हम आर्गुमेंट की संख्या बदल सकते हैं:
julia> f(x, y) = x * y
f (generic function with 4 methods)
लगता है कि एक ही फंक्शन की नई परिभाषाओं को "मेथड" कहा जाता है। पुरानी परिभाषा को मिटाने के बजाय मेथड एक सूची में जोड़े जाते हैं।
हम मेथड की सूची आसानी से देख सकते हैं:
julia> methods(f) # output edited for brevity
# 4 methods for generic function "f" from Main:
[1] f(x, y)
[2] f(x::Integer)
[3] f(x::Real)
[4] f(x)
अगर हम फंक्शन f को कॉल करते हैं, तो Julia को किसी तरह पता चल जाता है कि कौन-सा मेथड इस्तेमाल करना है:
julia> f(2.5) # Float64
6.25
julia> f(2) # Int64
4
julia> f(2, 3) # Int64, Int64
6
मैनुअल के मुताबिक, फंक्शन एक ऑब्जेक्ट है जो आर्गुमेंट के एक टपल को एक रिटर्न वैल्यू पर मैप करता है।
f(2, 3) में फंक्शन के आर्गुमेंट को हम आम तौर पर दो अलग-अलग चीज़ें मानते हैं, लेकिन कंपाइलर उन्हें एक ही टपल की तरह देखता है। यह एक ही आर्गुमेंट के लिए भी सच है (हालाँकि इसे साफ़ तौर पर दिखाने के लिए हमें एक कॉमा जोड़ना पड़ता है):
julia> typeof( (2, 3) )
Tuple{Int64, Int64}
julia> typeof( (2,) )
Tuple{Int64}
फंक्शन को एक ब्लैक बॉक्स मानकर हम कह सकते हैं कि अंदर एक टपल जाता है और बाहर एक रिटर्न वैल्यू आती है। अधिक औपचारिक रूप से कहें तो टपल को एक रिटर्न वैल्यू पर मैप किया जाता है।
इसे आम तौर पर "पॉलिमॉर्फिज़्म" कहा जाता है।
यह कंप्यूटर साइंस में कई दशकों से एक बड़ा विषय रहा है, और इसके लिए अलग-अलग तरीके अपनाए गए हैं। Julia का तरीका अनोखा है, हालाँकि अकेला नहीं।
+ ऑपरेटर एक फंक्शन है जिसके 161 मेथड हैं)।... इसे कुछ हद तक बायपास कर सकता है)।dispatched किया जाता है, और वह एक परिणाम लौटाता है।MethodError उठती है।ध्यान दीजिए कि Julia डायनैमिकली टाइप्ड है, इसलिए मेथड डिस्पैच रन टाइम पर होता है।
पिछले हिस्से में बहुत सारे शब्द थे, तो चलिए उन विचारों को कोड में बदलते हैं। सरलता के लिए नीचे दिए सभी फंक्शन सिर्फ एक आर्गुमेंट लेते हैं, लेकिन दर्जनों आर्गुमेंट वाले फंक्शन मिलना कोई अनोखी बात नहीं है (जैसे प्लॉटिंग पैकेजों में या मशीन लर्निंग में)।
ज्यामितीय आकृतियों को दर्शाने के लिए पहले कुछ कस्टम टाइप बनाइए।
julia> abstract type Shape end
julia> struct Circle <: Shape
radius::Float64
end
julia> struct Square <: Shape
side::Float64
end
julia> struct Rectangle <: Shape
length::Float64
width::Float64
end
इसके बाद हम हर आकृति का क्षेत्रफल निकालने के लिए मेथड बना सकते हैं। हर मेथड एक आर्गुमेंट लेता है, और हर मामले में वह एक अलग कंक्रीट टाइप का होता है, जिसे उपयोगकर्ता ने खुद बनाया है।
julia> area(c::Circle) = π * c.radius^2
area (generic function with 1 method)
julia> area(s::Square) = s.side^2
area (generic function with 2 methods)
julia> area(r::Rectangle) = r.length * r.width
area (generic function with 3 methods)
अब हम कुछ आकृतियाँ बना सकते हैं और उनका क्षेत्रफल निकाल सकते हैं, और हर आकृति के लिए सही फॉर्मूला इस्तेमाल करने का काम Julia के डिस्पैच मेकैनिज़्म पर छोड़ सकते हैं।
julia> circle = Circle(2.3)
Circle(2.3)
julia> area(circle) # call signature Tuple{Circle}
16.619025137490002
julia> square = Square(1.6)
Square(1.6)
julia> area(square) # call signature Tuple{Square}
2.5600000000000005
julia> rectangle = Rectangle(1.4, 2.1)
Rectangle(1.4, 2.1)
julia> area(rectangle) # call signature Tuple{Rectangle}
2.94
मेथड सिग्नेचर डमी टाइप वैल्यू भी ले सकते हैं, लगभग उसी तरह जैसे पैरामेट्रिक टाइप लेते हैं।
इसका सिंटैक्स अलग है, क्योंकि इसमें एक where क्लॉज़ लगाना पड़ता है:
julia> same_type(v::Vector{T}, x::T) where {T} = true
same_type (generic function with 1 method)
julia> same_type([1, 2], 3)
true
julia> same_type([1, 2], "three")
ERROR: MethodError: no method matching same_type(::Vector{Int64}, ::String)
ऊपर के उदाहरण में दोनों आर्गुमेंट का एक ही टाइप T होना चाहिए, चाहे वह कोई भी हो।
T पर एक प्रतिबंध लगाकर हम इसे और स्पष्ट कर सकते हैं:
julia> same_type(v::Vector{T}, x::T) where {T<:Number} = true
same_type (generic function with 2 methods)
इस मेथड के साथ सिर्फ एक जैसे संख्यात्मक टाइप ही true लौटाते हैं।
एक से ज़्यादा डमी वेरिएबल भी हो सकते हैं, जिन्हें where क्लॉज़ में कॉमा से अलग किया जाता है।
julia> myfunc(a::S, b::T) where {S, T} = true
myfunc (generic function with 1 method)
मल्टीपल डिस्पैच बहुत लचीला है और Julia में बहुत अच्छा प्रदर्शन देता है, इसलिए इसका इस्तेमाल बहुत व्यापक रूप से होता है।
जैसा कि + के 161 मेथड का उदाहरण बताता है, Julia प्रोग्रामर कोशिश करते हैं कि मेथड ऐसे टाइप के साथ बनाएँ जो बहुत सटीक ढंग से तय किए गए हों।
बाइटकोड के स्तर पर दो पूर्णांक जोड़ना और दो दशमलव संख्याएँ जोड़ना बहुत अलग बात है, और एक पूर्णांक को एक दशमलव संख्या में जोड़ने पर टाइप प्रोमोशन की एक और उलझन जुड़ जाती है।
टाइप जितना ज़्यादा विशिष्ट होगा, कंपाइलर उतना ही ज़्यादा ऑप्टिमाइज़ेशन कर सकता है: Exercism के एक छोटे-से अभ्यास में इसका महत्व मामूली है, लेकिन जिन बड़े संख्यात्मक सिमुलेशनों के लिए Julia को बनाया गया है, उनमें प्रदर्शन के लिए यह बहुत ज़रूरी है।
अगर आप जानते हैं कि किसी मेथड को कौन-से इनपुट मिलेंगे, तो कंपाइलर को ज़रूर बताइए!
इस अभ्यास में आप एक ऐसा सिमुलेशन बनाएँगे जिसमें जीवों का आपस में सामना होता है। इससे आप Julia के मुख्य पैराडाइम, मल्टिपल डिस्पैच, की बुनियादी बातों से परिचित होंगे।
For this exercise, all function definitions should be a single-line declaration with no if/else logic.
आम तौर पर सामनों में एक इकाई a का दूसरी इकाई b से मिलना और उस पर प्रतिक्रिया देना शामिल होता है।
encounter(a, b) = "$(name(a)) meets $(name(b)) and $(meets(a, b))."
सबसे पहले हम यह सिमुलेशन बनाएँगे कि जब बिल्लियाँ और कुत्ते मिलते हैं, तो क्या होता है।
सबसे पहले एक एब्सट्रैक्ट टाइप Pet जोड़िए।
फिर Cat और Dog टाइप को Pet का सबटाइप बनाइए। इन दोनों में सिर्फ़ एक फील्ड होती है, जिसका नाम name है।
एक फंक्शन name() बनाइए जो किसी पालतू जानवर का नाम लौटाता है।
julia> fido = Dog("Fido")
Dog("Fido")
julia> name(fido)
"Fido"
नीचे दिए गए सामनों के लिए meets() मेथड बनाइए:
julia> ginger = Cat("Ginger")
Cat("Ginger")
julia> meets(ginger, fido)
"hisses"
एक ही मेथड वाला encounter() फंक्शन बनाइए, जो बताए कि जब दो नाम वाली इकाइयाँ मिलती हैं, तो क्या होता है।
julia> encounter(ginger, fido)
"Ginger meets Fido and hisses."
अगर टहलते समय उन्हें कोई और पालतू जानवर मिल जाए, जैसे कोई घोड़ा, तो क्या होता है?
julia> bella = Horse("Bella")
Horse("Bella")
julia> encounter(fido, bella)
"Fido meets Bella and is cautious."
पालतू जानवरों को ऐसी बहुत सी और चीज़ें भी मिल सकती हैं जो पालतू नहीं हैं: कारें, मनुष्य, पौधे, प्राकृतिक आपदाएँ, क्षुद्रग्रह… तब क्या होता है?
julia> colnago = Bicycle("Colnago")
Bicycle("Colnago")
julia> encounter(ginger, colnago)
"Ginger meets Colnago and runs away."
हमारे सिमुलेशन में और भी बहुत से सामने हो सकते हैं। एक कार कुत्ते से मिल सकती है, दो इलेक्ट्रॉन आपस में मिलकर एक-दूसरे पर असर डाल सकते हैं…
सारे सामनों को पहले से तय करना असंभव है, इसलिए हम एक जेनेरिक फॉलबैक बनाएँगे।
julia> γ1 = Photon("γ1")
Photon("γ1")
julia> γ2 = Photon("γ2")
Photon("γ2")
julia> encounter(γ1, γ2)
"γ1 meets γ2 and nothing happens."
# This is true, photons just pass through each other.
Exercism पर साइन अप कीजिए और Julia को 35 कॉन्सेप्ट128 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।