2013-01-21 28 views
5

मैं गो में एक पैकेज लिखने की कोशिश कर रहा हूं जो "जेनेरिक" प्रकार का उपयोग करके समीकरण की गणना करता है। विशिष्ट होने के लिए, मैं रनगे कुट्टा 5 सन्निकटन को कार्यान्वित करना चाहता हूं।जाओ (भाषा) सामान्य संख्यात्मक प्रकार/इंटरफ़ेस

यह सन्निकटन बिंदु t0 + h में एक (अज्ञात) समारोह y का मूल्यांकन t0 पर y का ही मूल्य, प्रारंभ समय t0, कदम चौड़ाई h और एक अंतर समीकरण dgl रूप dy/dt = g(t,y) जहां की है जो का उपयोग कर g कुछ फ़ंक्शन है।

यह अनुमान वैक्टरों (या यहां तक ​​कि matrices) के साथ काम करते समय स्केलर प्रकारों के साथ काम करते समय बिल्कुल वही व्यवहार करता है। अधिक आम तौर पर बोलते हुए: यह सब कुछ के साथ काम करता है जिसे एक ही प्रकार के मान में जोड़ा/घटाया जा सकता है और स्केलर द्वारा स्केल किया जा सकता है (जिसके लिए मैं float64 का उपयोग करता हूं)

इसलिए मैंने इसे गो इंटरफ़ेस के रूप में व्यक्त करने का प्रयास किया:

type Numeric interface { 
    Add(rhs Numeric) Numeric 
    Sub(rhs Numeric) Numeric 
    Mul(rhs float64) Numeric 
} 

लेकिन जब मैं इस इंटरफेस "लागू" करने की कोशिश, मैं क्योंकि मानकों की परेशानियों में भाग लिखें:

type Vec6F struct { 
    x, y, z float64 
    vx, vy, vz float64 
} 

func (lhs *Vec6F) Add(rhs *Vec6F) rk5.Numeric { 
    result := new(Vec6F) 
    result.x = lhs.x + rhs.x 
    result.y = lhs.y + rhs.y 
    result.z = lhs.z + rhs.z 
    result.vx = lhs.vx + rhs.vx 
    result.vy = lhs.vy + rhs.vy 
    result.vz = lhs.vz + rhs.vz 
    return result 
} 

यह मैं त्रुटि देता है

cannot use result (type *Vec6F) as type rk5.Numeric in return argument: 
     *Vec6F does not implement rk5.Numeric (wrong type for Add method 
       have Add(*Vec6F) rk5.Numeric 
       want Add(rk5.Numeric) rk5.Numeric 

जो एक हाथ पूरी तरह से तर्क पर है, मेरे लिए

लेकिन दूसरी तरफ (क्योंकि आरएचएस संख्यात्मक को लागू किसी अन्य वस्तु हो सकता है): मैं कैसे कि जाओ में की तरह कुछ व्यक्त करते हैं? सी ++ में मैं ऑपरेटर ओवरलोडिंग का उपयोग कर सकता हूं, लेकिन यह संभव नहीं है।

+0

"ऑफ-विषय": विभेदक समीकरण हल किया गया है जो सरल (सरल) मर्स कक्षा का वर्णन करता है। Quick'n'dirty पूर्ण कोड के लिए http://play.golang.org/p/GwehylBbLK –

उत्तर

2

जेनेरिक होने के लिए अपने Add विधि को Numeric पैरामीटर लेना चाहिए। इस से निपटने के लिए सामान्य तरीके से इस (on playground) की तरह एक प्रकार अभिकथन

func (lhs *Vec6F) Add(_rhs Numeric) Numeric { 
    result := new(Vec6F) 
    rhs := _rhs.(*Vec6F) // type assertion - will panic if wrong type passes 
    result.x = lhs.x + rhs.x 
    result.y = lhs.y + rhs.y 
    result.z = lhs.z + rhs.z 
    result.vx = lhs.vx + rhs.vx 
    result.vy = lhs.vy + rhs.vy 
    result.vz = lhs.vz + rhs.vz 
    return result 
} 

यदि आप विभिन्न प्रकार आप के बीच परिवर्तित करने के लिए चाहती थी तुम भी एक प्रकार स्विच इस्तेमाल कर सकते हैं के साथ है।

+0

Thx, शायद यह समाधान है जिसके साथ मैं समाप्त होने जा रहा हूं, हालांकि मुझे प्रकार के दावों को पसंद नहीं है। आप एक अपर्याप्त प्रति को सुरक्षित करने के लिए '_rhs। (Vec6F)' के बजाय एक सूचक प्रकार में कनवर्ट करते हैं, है ना? –

+0

टाइप धारणा कार्य करने के लिए इसे एक सूचक प्रकार होना था। मेरा मतलब यह देखने के लिए उपरोक्त खेल के मैदान लिंक पर इसे बदलने का प्रयास करें - आपको त्रुटि मिल जाएगी "असंभव प्रकार का दावा: Vec6F संख्यात्मक कार्यान्वित नहीं करता है (विधि जोड़ें पॉइंटर रिसीवर की आवश्यकता है)" –

1

वास्तव में, जेनेरिक जाने में समर्थित नहीं हैं। यदि आप किसी इंटरफ़ेस को कार्यान्वित करने के लिए एक प्रकार चाहते हैं, तो विधियों के प्रोटोटाइप को बिल्कुल मिलान करने की आवश्यकता है: आपको func (lhs *Vec6F) Add(rhs Numeric) Numeric की आवश्यकता होगी।

func (lhs *Vec6F) Add(rhs Numeric) Numeric { 
    vrhs := rhs.(*Vec6F) 
    result := new(Vec6F) 
    result.x = lhs.x + vrhs.x 
    result.y = lhs.y + vrhs.y 
    result.z = lhs.z + vrhs.z 
    result.vx = lhs.vx + vrhs.vx 
    result.vy = lhs.vy + vrhs.vy 
    result.vz = lhs.vz + vrhs.vz 
    return result 
} 

यह कम्पाइल और जब तर्क सही प्रकार के साथ कहा जाता है काम करना चाहिए, फिर भी, मैं इसे एक दुरुपयोग है कहेंगे:

यहाँ इस विधि लिखने के लिए एक प्रयास एक प्रकार दावे का उपयोग कर रहा है।

कुछ भी आपको स्केलर्स में वैक्टर जोड़ने के लिए इस विधि का उपयोग करने से रोकता है (रनटाइम त्रुटि को छोड़कर) क्योंकि वे दोनों Numeric लागू करेंगे। अंत में, आपको इंटरफ़ेस अबास्ट्रक्शन का उपयोग करने से कुछ भी नहीं मिलेगा।

गो दर्शन इस मामले में प्रकार-विशिष्ट तरीकों/कार्यों के उपयोग को निर्देशित करेगा।

+2

देखें "टाइप-विशिष्ट विधियों/कार्यों का उपयोग" से आपका क्या मतलब है? क्या आप एक उदाहरण दे सकते हैं? –

+0

जैसा कि, आपके पास एक सामान्य जोड़ नहीं होगा जो Vec6F और अन्य संख्यात्मक प्रकारों पर काम करता है। आपके पास addVec6F, आदि –

0

ऐसी दो समस्याएं हैं जिनमें आप चल रहे हैं।

1.) कारण यह संकलित नहीं करता है, और मेल खाने वाले इंटरफेस के बारे में शिकायत नहीं है क्योंकि Vec6F rk5 के लिए फ़ंक्शन हस्ताक्षर को संतुष्ट नहीं करता है। न्यूमेरिक। दोनों वापसी मान, और इनपुट पैरामीटर मिलान प्रकार होना चाहिए।

http://play.golang.org/p/kc9V9EXxJq फिक्स है कि समस्या लेकिन उसकी जगह एक नया ...

2.) विधि हस्ताक्षर मैच तो Vec6F संतुष्ट संख्यात्मक के हस्ताक्षर यह संपत्ति मूल्यों पर संख्यात्मक कार्रवाई करने की क्षमता को तोड़ दिया बनाने के लिए।ऐसा इसलिए है क्योंकि इंटरफेस में केवल विधियां हैं, कोई गुण नहीं है।

आपके उपयोगकेस में, क्या यह संख्यात्मक इंटरफ़ेस के लिए एक एक्सेसर विधि प्रदान करने के लिए समझ में आता है जो एक मैट्रिक्स सरणी लौटाएगा जो रिसीवर तब ऐड | सब | मल्टी ऑन करेगा? यह जटिल हो सकता है कि प्रत्येक इंटरफ़ेस कार्यान्वयन के तरीकों के भीतर क्या करने की आवश्यकता है, लेकिन मुझे लगता है कि आप जो चाहते हैं उसे प्राप्त करेंगे।

+1

होगा क्योंकि मुझे लगभग 2 घंटे पहले परिणाम (गणना के) की आवश्यकता थी, इसलिए मैंने फ्लोट 64 के स्लाइस का उपयोग करने के लिए कोड बदल दिया था, जो किसी भी तरह का एक्सेसर विधि प्रदान करने का एक मूलभूत संस्करण है। पूरा कोड http://play.golang.org/p/GwehylBbLK पर है - यह काम करता है, लेकिन यह मेरी राय में, अच्छा कोड होने से बहुत दूर है। एक्सेसर विधि के साथ समस्या निम्न है: मान लीजिए कि मुझे जटिल संख्याओं का उपयोग करना था। या मैं केवल एक अन्य उपयोग मामले में इंटीजर मूल्यों को चाहता हूं। एक एक्सेसर प्रदान करना संभवतः असंभव हो जाता है, क्योंकि मैं केवल वैक्टर/मैट्रिस पर काम नहीं कर सकता बल्कि बहुपदों पर भी काम करता हूं। –