2012-07-15 12 views
5

पर क्लोजर बनाएं मैं कुछ ऐसा करने की कोशिश कर रहा हूं जो मुझे यकीन नहीं है कि स्कैला के प्रकार की प्रणाली मुझे करने की अनुमति देगी।जेनेरिक से Scala

मैं मूल रूप से एक सामान्य परिभाषा से बंद करना चाहता हूं और उसी प्रकार के फ़ंक्शन को आंतरिक रूप से निष्पादित करते समय बंद कर देता हूं।

उदाहरण के लिए:

val f = async[(str:String, i:Int, b:BigInt) => Unit]({ (String, Int, BigInt) => 
    // Code here... 
}) 

// 'f' would have a type of (String, Int, BigInt) => Unit and would wrap the passed anonymous function 

एक परिभाषा के सैद्धांतिक उदाहरण:

def async[T](
    shell: Shell, 
    success: T, 
    failure: (Throwable) => Unit): T = { 
     new T { 
      val display = shell.getDisplay() 
      display.asyncExec(new Runnable() { 
      def run(): Unit = { 
       try { 
       success(_) 
       } catch { 
       case e:Throwable => 
        failure(e) 
       } 
      } 
      }) 
     } 
    } 

यह तो मुझे SWT के लिए अतुल्यकालिक कॉलबैक बनाने का एक सरल प्रणाली है करने की अनुमति होगी, से बाहर SWT रखते हुए मेरी व्यापार का तर्क।

+0

[स्कैला जेनिक्स के संभावित डुप्लिकेट - मैं जेनेरिक क्लास के अंदर पैरामीट्रिज्ड ऑब्जेक्ट क्यों नहीं बना सकता?] (Http://stackoverflow.com/questions/5336648/scala-generics-why-i-cant-create-parametrised- ऑब्जेक्ट-इन-जेनेरिक-क्लास) –

+0

मुझे नहीं लगता कि यह 100% डुप्लिकेट है, क्योंकि यदि मैं एक लागू विधि के साथ टाइप प्रकार टी बना देता हूं, तो मुझे अभी भी टी द्वारा प्रदान किए गए उचित मानकों को लेने की आवश्यकता होगी। , मिरर टाइप करें इस विशेष समस्या को हल करने के लिए असंभव हो सकता है। – Hakkar

उत्तर

9

आप Shapeless पुस्तकालय के साथ और अधिक सामान्य रूप से यह कर सकते हैं हम wrap इस प्रकार निर्धारित करें:

import shapeless._, Functions._ 

def wrap[F, A <: HList, R](f: F)(implicit 
    h: FnHListerAux[F, A => R], 
    u: FnUnHListerAux[A => R, F] 
): F = { (args: A) => 
    println("Before f") 
    val result = f.hlisted(args) 
    println("After f") 
    result 
}.unhlisted 

और उसके बाद इसका उपयोग कर सकते हैं:

scala> val sum: (Int, Int) => Int = _ + _ 
sum: (Int, Int) => Int = <function2> 

scala> val wrappedSum = wrap(sum) 
wrappedSum: (Int, Int) => Int = <function2> 

scala> wrappedSum(100, 1) 
Before f 
After f 
res0: Int = 101 

यह किसी भी धर्मार्थ के कार्य के साथ काम करता है।

तो स्कैला में यह संभव है, हालांकि बिना बेकार के कुछ समकक्ष करना लगभग निश्चित रूप से एक बड़ा सिरदर्द होगा।

+0

यह बहुत ही दिलचस्प लग रहा है! और यह किसी भी (महत्वपूर्ण) रनटाइम ओवरहेड को लागू नहीं करता है, उदाहरण के लिए, प्रतिबिंब का उपयोग करके? –

+0

नहीं, कोई प्रतिबिंब नहीं। प्रकार के वर्गों में कुछ होगा रनटाइम ओवरहेड, लेकिन यह अत्यधिक नहीं होना चाहिए। –

+0

धन्यवाद। यह वही है जो मैं चाहता था। यह अज्ञात वर्गों को अज्ञात कार्यों में परिवर्तित करने के लिए वास्तव में उपयोगी पैटर्न बन सकता है। – Hakkar

2

कैसे इन पंक्तियों के साथ कुछ के बारे में:

scala> def wrap[T1, T2, T3, R](f: (T1, T2, T3) => R) = { 
| (v1: T1, v2: T2, v3: T3) => 
|  println("Before f") 
|  val r = f(v1, v2, v3) 
|  println("After f") 
|  r 
| } 
wrap: [T1, T2, T3, R](f: (T1, T2, T3) => R)(T1, T2, T3) => R 

scala> def foo(x: String, y: Int, z: BigInt) = (x, y, z) 
foo: (x: String, y: Int, z: BigInt)(String, Int, BigInt) 

scala> val wrapped = wrap(foo _) 
wrapped: (String, Int, BigInt) => (String, Int, BigInt) = <function3> 

scala> wrapped("foo", 42, 12345) 
Before f 
After f 
res0: (String, Int, BigInt) = (foo,42,12345) 

तो समारोह आप रैप करने के लिए तर्क तो आप करेंगे, दुर्भाग्य से, प्रत्येक अलग arity के लिए एक बार अपने रैप समारोह को परिभाषित करने के लिए है कि विभिन्न संख्या में हो सकता था चाहते हैं: - । (

+0

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

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