2010-11-17 9 views
5

C++ में मैं क्या कर सकते हैं निम्नलिखित:सी ++ टेम्पलेट्स के समान स्कैला में जेनेरिक रिटर्न प्रकारों को कोड करना संभव है?

template<typename T, typename V> 
struct{ 
    void operator()(T _1, V _2){ 
     _2.foo(_1); 
    } 
}; 
मुझे मनमाने ढंग से किसी भी वस्तु जो कुछ विधि "foo" कहा जाता है कि के अग्रिम या तो तर्क प्रकार में निर्दिष्ट किए बिना कुछ प्रकार "टी" लेता है उपयोग करने के लिए तय कर सकते हैं जो

"foo" फ़ंक्शन और न ही कार्य का रिटर्न प्रकार।

जब मैं स्काला को देखो, Function1 की तरह लक्षण देखते हैं, और

def foo[T<:{def foo():Unit}](arg:T) = //something 
def bar(x:{def foo():Unit}) = //something 
def baz[T,V<:Function1[T,_]](x:T, y:V) = y(x) 

की तरह समारोह परिभाषा के साथ चारों ओर खेल रहा हूँ मैं अपने आप को देखो और लगता है कि कारण है कि मैं एक ही बात नहीं कर सकते? "बाज़" क्यों कोई लौटाता है? क्या यह संकलन समय पर वास्तविक रिटर्न प्रकार को कम नहीं कर सकता है? अगर मैं इसका उपयोग भी नहीं कर सकता तो मुझे "foo" का रिटर्न प्रकार क्यों घोषित करना होगा?

मैं

def biff[T,V:{def foo(x:T):Unit}] = //something 

या

def boff[T<:{def foo(x:Double):_}](y:T) = y.foo _ 

आप यह कर सकते हैं ऐसा करने में सक्षम होना चाहते हैं और मैं बस कुछ याद आ रही है? या यदि नहीं, तो क्यों नहीं?

+0

मैं 'biff' उदाहरण पर स्पष्ट नहीं हूं। क्या कोई गुम तर्क है? –

+0

@Aaron Novstrup कोई गुम तर्क नहीं। मुझे एक त्रुटि मिल रही है जब मैं इसे इस तरह बताता हूं। कहते हैं कि मैं "वी" को परिभाषित नहीं कर सकता हूं कि यह "टी" पर निर्भर करता है। – wheaties

उत्तर

11

अद्यतन:

असल में, आप ज्यादा बेहतर कर सकते हैं, और प्रकार inferencer होगा यदि आपको मदद की:

def baz[T,R,V](x:T, y:V)(implicit e: V <:< (T => R)) = e(y).apply(x) 

scala> baz(1, (i: Int) => i+1) 
res0: Int = 2 
:

def boff[T,R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _ 

baz के लिए, उसी तकनीक का प्रकार निष्कर्ष में सुधार होगा

आप करी से बेहतर कर सकते हैं:

def baz[T,R](x: T)(f: T => R) = f(x) 

पहले समाधान:

प्रकार inferencer आप के लिए T प्रकार की आपूर्ति करेगा, लेकिन आप कर सकते हैं:

class Boff[T] { 
    def apply[R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _ 
} 
object boff { 
    def apply[T] = new Boff[T] 
} 
+0

+1 यह चालाक है। –

2

foo के लिए:

def foo[R,T<:{def foo():R}](arg:T) = ... 

baz के मामले में, आप कहते हैं कि V किसी प्रकार से T से एक फ़ंक्शन होना चाहिए। यह प्रकार परिणाम प्रकार में प्रकट नहीं हो सकता है: आप इसे कैसे लिख सकते हैं? तो संकलक केवल अनुमान लगा सकता है कि परिणाम प्रकार Any है। आप इसे एक नाम दे अगर, हालांकि, आप

scala> def baz[T,R,V<:Function1[T,R]](x:T, y:V) = y(x) 
baz: [T,R,V <: (T) => R](x: T,y: V)R 
6

स्काला और सेल्सियस के बीच बुनियादी अंतर मिलता ++ कि स्काला में प्रत्येक वर्ग के एक बार संकलित किया गया है, और फिर उपलब्ध हो जाता है के रूप में है कि यह इस पर निर्भर करता कुछ भी साथ प्रयोग के लिए , जबकि सी ++ में एक टेम्पलेटेड क्लास को प्रत्येक नई निर्भरता के लिए संकलित किया जाना चाहिए।

तो, वास्तव में, एक सी ++ टेम्पलेट एन संकलित कक्षाएं उत्पन्न करता है, जबकि स्कैला केवल एक उत्पन्न करता है।

क्या यह संकलन समय पर वास्तविक रिटर्न प्रकार को कम नहीं कर सकता है?

क्योंकि क्लास संकलित होने के समय यह तय किया जाना चाहिए, जो इसका उपयोग संकलित होने के समय से भिन्न हो सकता है।

+0

धन्यवाद डैनियल। आप हमेशा एक महान "क्यों" प्रदान करते हैं। – wheaties

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

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