2011-02-07 20 views
7

को देखते हुए के साथ प्रयोग किया है:आंशिक समारोह आवेदन समय से पहले ही codeblock चलता है जब अंडरस्कोर

save(throw new RuntimeException("boom!"))(_) -> (Boolean) => Unit = <function1> //as expected 
save(throw new RuntimeException("boom!")) _ -> exception thrown 

:

save("test")(true) -> running f 
save("test")(false) -> not running f 
save(throw new RuntimeException("boom!"))(false) -> not running f 
save(throw new RuntimeException("boom!"))(true) -> running f and then exception thrown 

यहाँ आंशिक आवेदन के साथ उत्सुक व्यवहार है:

def save(f: => Any)(run:Boolean) { if (run) { println("running f"); f } else println("not running f") } 

मैं इसके साथ कॉल कर सकते हैं फ़ंक्शन के रूप में पास किए बिना कोडब्लॉक का तत्काल मूल्यांकन किया जाता है। उपरोक्त 2 कथनों के बीच क्या अंतर है?

+1

आप यहां कुछ स्पष्टीकरण पा सकते हैं: http://stackoverflow.com/questions/2363013/in-scala-why-cant-i-partially-apply-a-function-without-explicitly-specifying-it –

+3

IMHO, यह एक बग है। –

उत्तर

2

पहला मामला,

save(throw new RuntimeException("boom!")) _ 
"Scala Reference" (§6.7), अनुगामी अंडरस्कोर तर्क सूची के स्थान पर प्रयोग किया जाता है, और अभिव्यक्ति

val f: (Boolean) => Unit = save(throw new RuntimeException("boom!")) 

जहां पहले में बदल जाती है के अनुसार

def save का तर्क तुरंत मूल्यांकन किया जाता है।

अभिव्यक्ति ई _ अच्छी तरह से बनाई है, तो ई विधि प्रकार का है या यदि ई एक कॉल-दर-नाम पैरामीटर है। यदि ई पैरामीटर के साथ विधि है, तो _ का प्रतिनिधित्व करता है और ईटा विस्तार (§6.26.5) द्वारा फ़ंक्शन प्रकार में परिवर्तित किया जाता है। यदि ई पैरामीटर रहित विधि या कॉल-बाय-नाम प्रकार => टी के पैरामीटर, ई _ प्रकार() => टी का कार्य करता है, जो मूल्यांकन करता है जब यह खाली पैरामीटर सूची() पर लागू होता है ।

आपकी अपेक्षा के अनुरूप चीजें काम करने के लिए, कुछ संशोधनों की आवश्यकता है:

scala> def save(f:() => Any)(run:Boolean) { if (run) { println("running f"); f() } else println("not running f") } 
save: (f:() => Any)(run: Boolean)Unit 

scala> val f = save(() => throw new RuntimeException("boom!")) _ 
f: (Boolean) => Unit = <function1> 

scala> f(true) 
running f 
java.lang.RuntimeException: boom! 
     at $anonfun$1.apply(<console>:6) 

दूसरा मामला,

save(throw new RuntimeException("boom!"))(_) 

"Scala Reference" (§6.23), जब प्लेसहोल्डर है के अनुसार एक तर्क के प्रतिस्थापन के रूप में उपयोग किया जाता है, अभिव्यक्ति को

0 में परिवर्तित किया गया है
+1

वास्तव में, उद्धृत विनिर्देश के अनुसार मैं नाम से काम करने के लिए कॉल की उम्मीद करता हूं। आखिरकार, उस मामले में 'ई' का मूल्यांकन केवल खाली पैरामीटर सूची पर लागू होने पर किया जाता है। –

+0

मैं डैनियल से सहमत हूं। यदि स्पेक कहता है कि कॉल() => टी में परिवर्तित हो जाता है तो फ़ंक्शन का मूल्यांकन तब तक नहीं किया जाएगा जब तक इसे लागू नहीं किया जाता है। – ssanj

0

ईटा विस्तार के तहत कॉल-बाय-नाम पैरामीटर का व्यवहार वर्तमान में समीक्षा अधीन है, this bug देखें। आपका कोड काम करता है जैसा कि आप उम्मीद करते हैं (यानी, लाइन save(throw new RuntimeException("boom!")) _ अपवाद फेंकने के बिना एक फ़ंक्शन देता है) हाल ही में रात 2.10 के निर्माण के साथ। चलो देखते हैं कि यह रिलीज होने तक रहता है!

ईटा विस्तार के सामान्य मामले पर संबंधित प्रश्न के लिए this question भी देखें, जिसमें कॉल-बाय-नाम शामिल नहीं है।