2011-07-08 7 views
9

सवालस्कैला में एक प्रकार के प्रक्षेपण पर विशेषज्ञ कैसे करें?

का विवरण एक प्रकार T कि एक सार प्रकार सदस्य A शामिल पर विचार करें:

trait T { 
    type A 
} 

मैं एक वर्ग है कि एक प्रकार पैरामीटर के रूप में एक T0 <: T लेता है बनाना चाहते हैं, लेकिन माहिर पर प्रक्षेपणT0#A पर टाइप करें। उदाहरण के लिए, निम्न में, विधि foo विशिष्ट हो सकती है? @specialized साथ T0 व्याख्या वांछित परिणाम प्राप्त नहीं होगा

class Foo[T0 <: T] { 
    def foo(a: T0#A, f: T0#A => T0#A) = f(a) 
} 

ध्यान दें कि। foo टाइप प्रोजेक्शन T#A पर विशेषज्ञता का कोई अच्छा तरीका है?

एक सीमित समाधान: अतिरिक्त पैरामीटर

साथ विशेष माता पिता वर्ग से विरासत इस विशेष मामले में, यहाँ एक तरह से T0#A विशेषज्ञता हासिल करने में है:

trait SpecializedFoo[@specialized A0, T0 <: T] { 
    def foo(a: A0, f: A0 => A0) = f(a) 
} 
class Foo2[T0 <: T] extends SpecializedFoo[T0#A, T0] 

विशेष माता पिता वर्ग SpecializedFoo से इनहेरिट तक , हम सुनिश्चित करते हैं कि Foo2.foo विशिष्ट है।

विशेषज्ञता के सत्यापन

, कि Foo2.foo, लेकिन नहीं Foo.foo सत्यापित करने के लिए

trait ExplicitT extends T { 
    type A = Double 
} 

object Test { 
    def test1 = (new Foo[ExplicitT]).foo(1.0, _ + 1.0) 
    def test2 = (new Foo2[ExplicitT]).foo(1.0, _ + 1.0) 
} 

बाईटकोड कर सकते हैं हम उन्हें एक स्पष्ट T जहां T#A एक आदिम डबल है के साथ कॉल कर सकते हैं, विशेष है, कमांड के साथ आरईपीएल से जांच की जा सकती है ": javap -v test",

public double test1(); 
    Code: 
    Stack=4, Locals=1, Args_size=1 
    0: new #16; //class Foo 
    3: dup 
    4: invokespecial #18; //Method Foo."<init>":()V 
    7: dconst_1 
    8: invokestatic #24; //Method scala/runtime/BoxesRunTime.boxToDouble:(D)Ljava/lang/Double; 
    11: new #26; //class Test$$anonfun$test1$1 
    14: dup 
    15: invokespecial #27; //Method Test$$anonfun$test1$1."<init>":()V 
    18: invokevirtual #31; //Method Foo.foo:(Ljava/lang/Object;Lscala/Function1;)Ljava/lang/Object; 
    21: invokestatic #35; //Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D 
    24: dreturn 
    LineNumberTable: 
    line 13: 0 


public double test2(); 
    Code: 
    Stack=5, Locals=1, Args_size=1 
    0: new #38; //class Foo2 
    3: dup 
    4: invokespecial #39; //Method Foo2."<init>":()V 
    7: dconst_1 
    8: new #41; //class Test$$anonfun$test2$1 
    11: dup 
    12: invokespecial #42; //Method Test$$anonfun$test2$1."<init>":()V 
    15: invokeinterface #48, 4; //InterfaceMethod SpecializedFoo.foo$mcD$sp:(DLscala/Function1;)D 
    20: dreturn 
    LineNumberTable: 
    line 14: 0 

ध्यान दें कि मुक्केबाजी test1 में दिखाई देती है लेकिन test2 नहीं है।

सीमाएं

संपादित 7/9 चाल ऊपर और अधिक सीमित की तुलना में मैं पहली बार में महसूस किया है। यह बिल्कुल भी इस मामले विशेषज्ञता के लिए काम नहीं करेगा:

trait T { 
    type A 
    def x: A 
    def f: A => Double 
} 

class Foo[T0 <: T] { 
    def foo(t: T0) = t.f(t.x) 
} 

मुझे कोई कारण नहीं क्यों एक (काल्पनिक) संकलक Aसिद्धांत में पर विशेषज्ञ नहीं कर सकता है; एक सामान्य, विशेष संस्करण केवल प्रयोग योग्य होंगे जब एक विशिष्ट T#A संकलन समय पर जाना जाता है। प्राकृतिक व्यावहारिक समाधान A को T के प्रकार पैरामीटर में उठाना है, लेकिन मैं सोच रहा था कि क्या मैं इससे बच सकता हूं।

उत्तर

1

यह एक संकलक सीमा है; एक आमतौर पर एक प्रकार पैरामीटर के तत्वों पर विशेषज्ञ नहीं हो सकता है। हालांकि, प्रस्तावित चाल मेरी प्रयोजनों के लिए काफी अच्छा है:

trait Types { 
    type A 
    type B 
} 

trait GenOps[@specialized A, @specialized B] { 
    ... 
} 

trait Ops[T <: Types] extends GenOps[T#A, T#B] 

इस तरह विशेषता Ops विशेष हो जाता है, क्योंकि यह विशेषता GenOps में विशेष कार्यान्वयन इनहेरिट करती है। मेरी प्रेरणा यह है कि मुझे Ops और T#B दोनों के बजाय एक प्रकार का पैरामीटर T लेना चाहिए (यह आवश्यक हो जाता है जब Ops एक उच्च प्रकार का प्रकार भी लेता है जो T पैरामीटर के रूप में अपेक्षा करता है)।

1

मैं नहीं देख सकता कि यह संभवतः कैसे काम कर सकता है। वर्ग को संकलित करते समय विशेषज्ञता की जाती है, और उस समय, A ज्ञात नहीं है।

+0

विचार यह है कि मैं एक कार्यान्वयन 'कक्षा बार पर विशेष विधियों को चाहता हूं जो फू [एस]' बढ़ाता है, जहां 'एस <: टी' संकलित समय पर स्पष्ट रूप से जाना जाता है और 'एस # ए' एक आदिम है। मुझे पता है कि यह काम कर सकता है क्योंकि ऊपर की चाल का उपयोग (यानी, एक अतिरिक्त प्रकार पैरामीटर वाला 'स्पेशलफू' पैरेंट क्लास) मैं मुक्केबाजी को खत्म करने में सक्षम था, जिसे मैंने स्कैला आरपीएल में ": जावा-वी" के साथ सत्यापित किया था। प्रश्न में नमूना कोड निश्चित रूप से एक सरलीकरण है ... शायद मुझे और विवरण देना चाहिए। –

+0

मैंने इस प्रश्न को अद्यतन किया कि मुक्केबाजी कैसे दिखाई देती है, और विशेषज्ञता के साथ इसे कैसे हटाया जा सकता है। –

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