2011-10-07 10 views
6

निम्न कोड उदाहरण में, मुझे समझ में नहीं आता कि फ़ंक्शन मज़े विधि addAction पर तर्क के रूप में क्यों पारित किया जा सकता है। विधि fun प्रकार Unit है, जबकि विधि addAction() => Unit प्रकार के फ़ंक्शन की अपेक्षा करता है।स्केल विधि प्रकार और विधियों पैरामीटर

तो fun,, प्रकार () => Unit की है तो क्यों संकलक शिकायत है कि fun प्रकार Unit की है जब मैं कार्यों की सूची पर fun जोड़ने का प्रयास: actions = fun :: actions?

package myscala 

object MyScala { 

    def fun() { println("fun1 executed.") } 

    def addAction(a:() => Unit) { 
    actions = a :: actions 
    } 

    var actions: List[() => Unit] = List() 

    def main(args: Array[String]) { 
    // the following line would produce a compiler error (found: Unit, required:() => Unit), it's OK 
    // actions = fun :: actions 
    actions = (() => fun) :: actions // OK 
    // I would expect the same compiler error here (found: Unit, required:() => Unit), but it's OK why? 
    addAction(fun) 
    actions.foreach(_()) // prints twice "fun1 executed" 
    } 
} 

उत्तर

8

एक परिचयात्मक उदाहरण के रूप में यह लो। हालांकि a1 प्रकार Unit है जबकि a2() => Unit प्रकार है ... यह कैसे संभव है?

के बाद से आप स्पष्ट रूप से a1 के प्रकार प्रदान नहीं कर रहे, व्याख्या compilers fun प्रकार Unit की एक विधि fun फोन के रूप में है, इसलिए a1 के प्रकार fun के प्रकार के रूप में ही है। इसका मतलब यह भी है कि यह लाइन fun1 निष्पादित की जाएगी।

हालांकि, a2 ने स्पष्ट रूप से () => Unit का प्रकार घोषित कर दिया है। कंपाइलर आपको यहां मदद करता है और यह समझता है कि संदर्भ के लिए () => Unit प्रकार के फ़ंक्शन की आवश्यकता होती है और आपने इस प्रकार से मेल खाने वाली विधि प्रदान की है, इसे उस विधि को कॉल नहीं करना चाहिए, लेकिन इसे प्रथम श्रेणी के फ़ंक्शन के रूप में देखें!

आप a1 को स्पष्ट रूप से निर्दिष्ट करने के लिए बर्बाद नहीं हैं। कह रहा है:

val a1 = fun _ 

क्या अब आप समझते हैं कि आपकी समस्या कहां है?

+0

हाँ, मैं करता हूं। यह अब मुझे स्पष्ट दिखता है (यह उस समय बिल्कुल नहीं था)। जब संकलक यह अनुमान लगाने में सक्षम होता है कि फ़ंक्शन प्रकार की अपेक्षा की जाती है, तो मैं बस 'मजेदार' लिख सकता हूं, अन्यथा मुझे यह स्पष्ट करना होगा कि मैं एक फ़ंक्शन पास कर रहा हूं। आप सभी के स्पष्ट जवाब के लिए धन्यवाद! – Manu

+0

@ मॅनू: एक उत्तर स्वीकार करने पर विचार करें जिसे आप सबसे अच्छा मानते हैं (यह आवश्यक नहीं है) –

5

आप पहले मामले में fun _ लिखने के लिए विधि बुला और बदले ईटा-विस्तार प्रदर्शन कर से बचने के लिए की जरूरत है।

यह काम करेगा:

actions = (fun _) :: actions 

यदि आप ऐसा नहीं करते हैं, तो fun मूल्यांकन किया जाता है।

अधिक जानकारी के लिए, धारा 6.7 (विधि मान) Scala Language Reference के देखते हैं।

क्यों fun का मूल्यांकन दूसरे मामले में नहीं किया जाता है, ऐसा इसलिए है क्योंकि टाइप अनुमान से स्पष्ट रूप से निष्कर्ष निकाला जा सकता है कि addAction फ़ंक्शन की अपेक्षा करता है। वैसे, fun का प्रकार तकनीकी रूप से ()Unit है, Unit नहीं, यानी एक विधि प्रकार है, न कि मूल्य प्रकार। अधिक के लिए reference में खंड 3.3.1 देखें। (अनुमान टाइप करने के लिए धन्यवाद) वे बराबर लग

def fun() { println("fun1 executed.") } 

val a1 = fun 
val a2:() => Unit = fun 

दोनों लाइनों संकलन और:

+3

मैं नहीं बल्कि एक लाइटर पढ़ने की सलाह देते हैं अध्याय 9] (http://www.artima.com/pins1ed/control-abstraction.html) – Jamil

3

विधियों और कार्यों के बीच एक अंतर है। आपके मामले में actions फ़ंक्शंस की एक सूची है।जब संकलक जानता है कि एक फ़ंक्शन आवश्यक है (जैसे addAction के मामले में) यह स्वचालित रूप से एक कार्य में fun विधि को परिवर्तित कर सकता है। अब :: भी एक विधि है, इसलिए संकलक यह भी जानता है कि यह पैरामीटर के रूप में कार्य करता है। लेकिन समस्या दाएं-सहयोगी ऑपरेटर :: की सिंटैक्टिक चीनी है। यदि आप इसे एक विधि की तरह कॉल करना चाहते थे: actions.::(fun) यह संकलित करेगा (हालांकि मैं इस समय इसका परीक्षण नहीं कर सकता)। fun :: actions लिखते समय संकलक सोचता है कि fun एक अभिव्यक्ति है और इसलिए इसका मूल्यांकन होता है और चूंकि यह Unit "रिटर्न" करता है तो आपको अपनी कंपाइलर त्रुटि मिलती है।

संपादित

के बाद से अब मैं अपने परिकल्पना (जो गलत था) यहाँ विकल्प हैं परीक्षण करने के लिए संभावना है: स्काला में [प्रोग्रामिंग:

// Usual syntax 
actions.::[() => Unit](fun) 
actions.::(fun:() => Unit) 
actions.::(fun _) 
// Operator syntax 
(fun:() => Unit) :: actions 
(fun _) :: actions 
+0

'क्रियाएं: :(मजेदार) 'सूची का मूल्यांकन' सूची [किसी भी] = सूची (())'। हालांकि यह अभी भी समारोह का मूल्यांकन कर रहा है। आश्चर्य है कि सूची क्यों है [() => इकाई] सूची में परिवर्तित [कोई]? सह विचरण? – Jamil

+2

हां, 'सूची [कोई भी]' एक सूची के लिए सबसे सटीक प्रकार है जिसमें 'यूनिट' और '() => यूनिट की हो सकती है। 'यूनिट', जिसे '()' के रूप में देखा जाता है, वह 'मजेदार' रिटर्न का मूल्यांकन करता है। – Philippe

+0

मैंने अपना जवाब संपादित कर लिया है। – agilesteel

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