2012-09-01 12 views
24

एक ट्यूपल तर्क को सबसे अच्छा तरीका कैसे पास किया जाए?एक ट्यूपल तर्क को सबसे अच्छा तरीका कैसे पास किया जाए?

उदाहरण:

def foo(...): (Int, Int) = ... 

def bar(a: Int, b: Int) = ... 

अब मैं bar को foo के उत्पादन में पारित करने के लिए करना चाहते हैं। इस के साथ प्राप्त किया जा सकता है:

val fooResult = foo(...) 
bar(fooResult._1, fooResult._2) 

यह दृष्टिकोण, एक सा बदसूरत लग रहा है, खासकर जब हम n > 2 के साथ एक n -tuple के साथ सौदा। इसके अलावा हमें foo का परिणाम अतिरिक्त मूल्य में संग्रहीत करना होगा, अन्यथा foo को bar(foo._1, foo._2) का उपयोग करके एक से अधिक बार निष्पादित किया जाना है।

क्या टुपल को तर्क के रूप में पारित करने का कोई बेहतर तरीका है?

val bar2 = (bar _).tupled // or Function.tupled(bar _) 

bar2(Int, Int) (एक ही bar के रूप में तर्क) के एक टपल लेता है:

+1

संभावित डुप्लिकेट [एक टुपल पर फ़ंक्शन कैसे लागू करें?] (Http://stackoverflow.com/questions/1987820/how-to-apply-a-function-to-a-tuple) –

उत्तर

39

एक विशेष tupled हर कार्य के लिए उपलब्ध विधि नहीं है। अब आप कह सकते हैं:

bar2(foo()) 

यदि आपका तरीकों वास्तव में थे कार्य (नोटिस val कीवर्ड) वाक्य रचना बहुत अधिक सुखद है:

val bar = (a: Int, b: Int) => //... 
bar.tupled(foo()) 

भी देखें

+0

धन्यवाद, यह वही है जिसे मैं देख रहा था। वह मेरे लिए चाल करेगा। अतिरिक्त प्रश्न: आपने बताया कि एक विधि और एक समारोह के बीच एक अंतर है - क्या अंतर है? मैं इसके बारे में और जानना चाहता हूं। क्या आप मुझे कुछ संदर्भ/लिंक दे सकते हैं जहां मैं इसके बारे में अधिक पढ़ सकता हूं? –

+3

@ जॉन थ्रीपवुड: स्कैला में विधियां जावा में विधियों का अनुवाद करती हैं। स्कैला में कार्य वस्तुओं के लिए अनुवाद। स्कैला में यह ज्यादातर पारदर्शी है ("* एटा-विस्तार *" के लिए खोजें), लेकिन कभी-कभी वाक्यविन्यास थोड़ा अलग होता है। [यह आलेख] (http://jim-mcbeath.blogspot.no/2009/05/scala-functions-vs-methods.html) बहुत व्यापक है। –

+0

ग्रेट, बहुत बहुत धन्यवाद। –

8

tupled का उपयोग करना, जैसा कि @ टोमाज़ उल्लेख है, एक अच्छा दृष्टिकोण है।

तुम भी काम के दौरान टपल foo से लौटे निकाल सकते:

val (x, y) = foo(5) 
bar(x, y) 

यह क्लीनर कोड (कोई _1 और _2) को लाभ मिलता है, और आप x और y के लिए वर्णनात्मक नाम निर्दिष्ट कर सकते हैं, जिससे आपके कोड पढ़ने के लिए आसान है।

+0

धन्यवाद। मैं सहमत हूं, यह अधिक पठनीय है। मैं उस चाल को दिमाग में रखूंगा। लेकिन अतिरिक्त मूल्य मुझे थोड़ा परेशान करता है। मैं परिणाम को अतिरिक्त मूल्य पर सहेजने के बिना इसे पारित करना चाहता हूं। लेकिन अभी भी इस संकेत के लिए धन्यवाद! –

5

यह लायक भी जानना है के बारे में

foo(...) match { case (a,b) => bar(a,b) } 

एक विकल्प है कि आप स्पष्ट रूप से एक अस्थायी fooResult बनाने के लिए की आवश्यकता नहीं है के रूप में। यह एक अच्छा समझौता है जब गति और अव्यवस्था की कमी दोनों महत्वपूर्ण हैं। आप bar _ के साथ एक फ़ंक्शन बना सकते हैं और फिर .tupled के साथ एक एकल टुपल तर्क लेने के लिए इसे परिवर्तित कर सकते हैं, लेकिन जब भी आप जोड़ी को कॉल करते हैं तो यह दो नई फ़ंक्शन ऑब्जेक्ट बनाता है; आप परिणाम स्टोर कर सकते हैं, लेकिन यह आपके कोड को अनावश्यक रूप से अव्यवस्थित कर सकता है।

हर रोज इस्तेमाल के लिए (यानी यह आपके कोड के प्रदर्शन को सीमित हिस्सा नहीं है), आप कर सकते हैं बस

(bar _).tupled(foo(...)) 
लाइन में

।निश्चित रूप से, आप दो अतिरिक्त फ़ंक्शन ऑब्जेक्ट्स बनाते हैं, लेकिन संभवतः आपने टुपल भी बनाया है, इसलिए आपको पर परवाह नहीं है, है ना?

+0

इस विकल्प को इंगित करने के लिए धन्यवाद। लेकिन वापसी के रूप में एक ट्यूपल क्यों प्रदर्शन के बारे में परवाह नहीं करने का संकेत है? लेकिन हाँ, आप सही हैं, मेरे कार्यक्रम में प्रदर्शन इससे कोई फर्क नहीं पड़ता। –

+0

@ जॉन थ्रीपवुड - आपको एक टुपल लौटने के लिए एक वस्तु बनाना है। यदि आप जो कुछ भी कर रहे हैं वह ऑब्जेक्ट सृजन की तुलना में महंगा है, तो संभवतः यह दो ऑब्जेक्ट रचनाओं की तुलना में महंगा है (जो आपको 'बार _' और '.tupled' के साथ मिलता है)। यदि आप ऑब्जेक्ट सृजन की तुलना में सस्ता कर रहे हैं, तो आपने ऑब्जेक्ट क्यों बनाया? आपको उस ऑब्जेक्ट में पारित होना चाहिए था जिसे आप सेट कर सकते हैं। (उत्तरार्द्ध दृष्टिकोण ऐसा कुछ है जो आपको शायद ही कभी करना चाहिए - ऑब्जेक्ट सृजन काफी सस्ते है।) –

+0

स्पष्टीकरण के लिए धन्यवाद। व्याख्या समझ में आता है, मैं इसे ध्यान में रखूंगा। –