2015-06-10 17 views
9

मैं अपनी फ़ंक्शन परिभाषा में फ़ंक्शन पैरामीटर के उप-प्रकार का उपयोग करना चाहता हूं। क्या यह संभव है?क्या मैं फ़ंक्शन परिभाषा में फ़ंक्शन पैरामीटर के उप प्रकार का उपयोग कर सकता हूं?

g{T1, T2<:T1}(x::T1, y::T2) = x + y 

ताकि g किसी भी x::T1 के लिए परिभाषित किया जाएगा और किसी भी yT1 की एक उप-प्रकार है: उदाहरण के लिए, मैं की तरह कुछ लिखने के लिए करना चाहते हैं। जाहिर है, अगर मुझे पता था, उदाहरण के लिए, T1 हमेशा Number होगा, तो मैं g{T<:Number}(x::Number, y::T) = x + y लिख सकता हूं और यह ठीक काम करेगा। लेकिन यह सवाल उन मामलों के लिए है जहां T1 रन-टाइम तक ज्ञात नहीं है।

पर पढ़ें आप सोच रहे हैं कि कारण है कि मैं ऐसा करना चाहते हैं:

मैं क्या थोड़ा बोझिल होगा करने के लिए कोशिश कर रहा हूँ, लेकिन क्या इस प्रकार एक सरल उदाहरण है का पूरा विवरण। के रूप में

abstract MyAbstract 
type MyType <: MyAbstract ; end 

मैं बनाने के इस प्रकार एक सार सुपर-प्रकार परिभाषित के साथ,

type MyVectorType{T} 
    x::Vector{T} 
end 
f1!{T}(m::MyVectorType{T}, xNew::T) = (m.x[1] = xNew) 

मैं भी एक और प्रकार है:

मैं एक parameterised प्रकार है, और एक सरल विधि है कि प्रकार पर परिभाषित वेक्टर तत्व प्रकार के साथ MyVectorType का उदाहरण MyAbstract पर सेट किया गया:

m1 = MyVectorType(Array(MyAbstract, 1)) 

अब मैं में MyType का उदाहरण देना चाहता हूं। मैं यह कर सकता हूं, MyType <: MyAbstract के बाद से। हालांकि, मैं f1! के साथ ऐसा नहीं कर सकता, क्योंकि फ़ंक्शन परिभाषा का अर्थ है कि xNewT प्रकार का होना चाहिए, और TMyAbstract होगा, MyType नहीं।

दो समाधान मैं इस समस्या के बारे में सोच सकते हैं:

f2!(m::MyVectorType, xNew) = (m.x[1] = xNew) 
f3!{T1, T2}(m::MyVectorType{T1}, xNew::T2) = T2 <: T1 ? (m.x[1] = xNew) : error("Oh dear!") 

पहले अनिवार्य रूप से एक बतख टाइपिंग समाधान है। दूसरा चरण में उचित त्रुटि जांच करता है।

कौन सा पसंदीदा है? या क्या कोई तीसरा, बेहतर समाधान है जिसके बारे में मुझे पता नहीं है?

उत्तर

11

फ़ंक्शन को परिभाषित करने की क्षमता g{T, S<:T}(::Vector{T}, ::S) को डायगोनल प्रेषण के समानता के रूप में "त्रिकोणीय प्रेषण" के रूप में संदर्भित किया गया है: f{T}(::Vector{T}, ::T)। (पंक्तियों और स्तंभों को लेबल करने वाले एक प्रकार के पदानुक्रम वाली तालिका की कल्पना करें, इस तरह व्यवस्थित किया गया है कि सुपर प्रकार ऊपर और बाएं हैं। पंक्तियां पहले तर्क के तत्व प्रकार का प्रतिनिधित्व करती हैं, और स्तंभ दूसरे के प्रकार का प्रतिनिधित्व करते हैं। विकर्ण प्रेषण केवल तालिका के विकर्ण के साथ कोशिकाओं से मेल खाते हैं, जबकि त्रिभुज प्रेषण विकर्ण और इसके नीचे सबकुछ से मेल खाता है, एक त्रिभुज बनाते हैं।)

यह अभी तक लागू नहीं किया गया है । यह एक जटिल समस्या है, खासकर जब आप T और S की कार्य परिभाषाओं के बाहर और आविष्कार के संदर्भ में स्कॉइंग पर विचार करना शुरू कर देते हैं। अधिक जानकारी के लिए issue #3766 और #6984 देखें।


तो, व्यावहारिक रूप से, इस मामले में, मुझे लगता है कि बतख-टाइपिंग ठीक है। आप त्रुटि को जांचने के लिए myVectorType के कार्यान्वयन पर भरोसा कर रहे हैं, जब यह उसके तत्वों को निर्दिष्ट करता है, जो इसे किसी भी मामले में करना चाहिए।

एक सरणी के तत्वों की स्थापना के लिए आधार जूलिया में समाधान कुछ इस तरह है: "। त्रिकोण"

f!{T}(A::Vector{T}, x::T) = (A[1] = x) 
f!{T}(A::Vector{T}, x) = f!(A, convert(T, x)) 

ध्यान दें कि यह प्रकार पदानुक्रम या उप-प्रकार के बारे में चिंता नहीं है यह सिर्फ x को T में परिवर्तित करने का प्रयास करता है ... x::S, S<:T यदि कोई नो-ऑप है। और convert एक त्रुटि फेंक देगा अगर यह रूपांतरण नहीं कर सकता है या नहीं जानता कि कैसे।


अद्यतन: यह अब नवीनतम विकास संस्करण (0.6-देव) पर लागू किया गया है! इस मामले में मुझे लगता है कि मैं अभी भी convert का उपयोग करने की अनुशंसा करता हूं जैसा कि मैंने मूल रूप से उत्तर दिया था, लेकिन अब आप स्थिर विधि पैरामीटर के भीतर बाएं से दाएं तरीके से प्रतिबंध परिभाषित कर सकते हैं।

julia> f!{T1, T2<:T1}(A::Vector{T1}, x::T2) = "success!" 

julia> f!(Any[1,2,3], 4.) 
"success!" 

julia> f!(Integer[1,2,3], 4.) 
ERROR: MethodError: no method matching f!(::Array{Integer,1}, ::Float64) 
Closest candidates are: 
    f!{T1,T2<:T1}(::Array{T1,1}, ::T2<:T1) at REPL[1]:1 

julia> f!([1.,2.,3.], 4.) 
"success!" 
+1

बहुत उपयोगी उत्तर - मैंने बहुत कुछ सीखा। बहुत धन्यवाद। –

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

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