2016-05-06 14 views
14

यह स्निपेट में आधार मामले के बिना समझना प्रत्यावर्तन जूलिया में Rational Numbers के कार्यान्वयन से है? यह वास्तव में एक मूल्य कैसे वापस करता है?जूलिया

मुझे इस कोड को देखा मैं इसे इस तरह से व्याख्या:

  1. // समारोह एक वाजिब और एक पूर्णांक के साथ कहा जाता है।
  2. लेकिन फिर यह किसी अन्य तर्क के साथ एक रिकर्सिव कॉल करता है।

# 2 वह है जो वास्तव में मुझे भ्रमित करता है। डेटा संरचना के भीतर रिकर्सन कहां समाप्त होता है? // एक मान वापस कैसे करता है यदि यह लगातार कुछ भी मूल्यांकन नहीं कर रहा है?

कृपया इसे समझने में मेरी सहायता करें।

उत्तर

12

यह जूलिया की सबसे मौलिक विशेषताओं में से एक के कारण काम करता है: एकाधिक प्रेषण। जूलिया में, फ़ंक्शंस में कई विधियां हो सकती हैं जो तर्क प्रकारों के विभिन्न संयोजनों पर लागू होती हैं, और जब आप कोई फ़ंक्शन कॉल करते हैं, तो जूलिया सबसे विशिष्ट विधि को आमंत्रित करती है जो आपके द्वारा बुलाए गए सभी तर्कों के प्रकार से मेल खाती है। // आपके द्वारा पोस्ट की गई विधि परिभाषा में कॉल पूर्णांक-पूर्णांक // पूर्णांक-पूर्णांक // के संदर्भ में तर्कसंगत-पूर्णांक // परिभाषित करता है - इसलिए यह वास्तव में रिकर्सिव नहीं है क्योंकि विधि स्वयं को कॉल नहीं करती है, यह एक अलग विधि कहती है जो " सामान्य कार्य "।

यह समझने के लिए कि इस मामले में एकाधिक प्रेषण कैसे काम करता है, आइए (3//4)//6 अभिव्यक्ति के मूल्यांकन पर विचार करें। हम @which मैक्रो का उपयोग यह देखने के लिए करेंगे कि प्रत्येक फ़ंक्शन कॉल किस विधि को आमंत्रित करता है।

julia> @which (3//4)//6 
//(x::Rational{T<:Integer}, y::Integer) at rational.jl:25 

3//4 के बाद से, एक Rational{Int} <: Rational और 6 एक Int <: Integer है, और कोई अन्य अधिक विशिष्ट विधियों लागू है इस विधि कहा जाता है:

//(x::Rational, y::Integer) = x.num // (x.den*y) 

विधि के current version वास्तव में थोड़ी भी अधिक जटिल है क्या आपने पोस्ट किया क्योंकि इसे पूर्णांक ओवरफ़्लो की जांच करने के लिए संशोधित किया गया है - लेकिन यह अनिवार्य रूप से वही है, और पुराने, सरल संस्करण को समझना आसान है, इसलिए मैं इसका उपयोग करूंगा। के x और y तर्क को असाइन करने और क्या विधि परिभाषा कॉल देखते हैं:

//(n::Integer, d::Integer) = Rational(n,d) 

:

julia> x, y = (3//4), 6 
(3//4,6) 

julia> x.num 
3 

julia> x.den*y 
24 

julia> x.num // (x.den*y) 
1//8 

julia> @which x.num // (x.den*y) 
//(n::Integer, d::Integer) at rational.jl:22 

आप देख सकते हैं, इस अभिव्यक्ति एक ही विधि फोन नहीं है, यह एक different method कॉल यह विधि केवल Rational कन्स्ट्रक्टर को कॉल करती है जो n और d का अनुपात निम्नतम शर्तों में डालती है और Rational संख्या ऑब्जेक्ट बनाता है।

जूलिया में एक ही कार्य की दूसरी विधि के संदर्भ में फ़ंक्शन की एक विधि को परिभाषित करना काफी आम है। उदाहरण के लिए, यह तर्क डिफ़ॉल्ट रूप से काम करता है।इस परिभाषा पर विचार करें:

julia> f(x, y=1) = 2x^y 
f (generic function with 2 methods) 

julia> methods(f) 
# 2 methods for generic function "f": 
f(x) at none:1 
f(x, y) at none:1 

julia> f(1) 
2 

julia> f(2) 
4 

julia> f(2,2) 
8 

डिफ़ॉल्ट तर्क वाक्य रचना बस केवल onee तर्क है, जो डिफ़ॉल्ट मान के साथ दो तर्क प्रपत्र कॉल के साथ एक दूसरी विधि उत्पन्न करता है। तो f(x, y=1) = 2x^y ठीक दो तरीकों, जहां एकल विधि सिर्फ द्विआधारी प्रणाली को बुलाती है परिभाषित करने, दूसरा तर्क लिए एक डिफ़ॉल्ट मान की आपूर्ति के बराबर है:

julia> f(x, y) = 2x^y 
f (generic function with 1 method) 

julia> f(x) = f(x, 1) 
f (generic function with 2 methods) 
+0

यह बहुत स्पष्ट अर्थ का था। धन्यवाद। – dopatraman