स्काला में एक फ़ंक्शन को परिभाषित करने के इन तीन तरीकों के बीच अंतर


92

समान कार्य को व्यक्त करने के तीन तरीके दिए गए हैं f(a) := a + 1:

val f1 = (a:Int) => a + 1
def f2 = (a:Int) => a + 1
def f3:(Int => Int) = a => a + 1

ये परिभाषाएँ कैसे भिन्न हैं? REPL किसी भी स्पष्ट अंतर को इंगित नहीं करता है:

scala> f1
res38: (Int) => Int = <function1>
scala> f2
res39: (Int) => Int = <function1>
scala> f3
res40: (Int) => Int = <function1>

11
आपको ध्यान देना चाहिए कि उपरोक्त 2 ब्लॉक f1में, REPL में मूल्यांकन, मूल्यांकन f1करते समय सांख्यिकीय रूप से बाध्य दिखाता है f2और उन तरीकों f3को लागू करने का परिणाम दिखाता है । विशेष रूप से, Function1[Int, Int]हर बार या तो एक नया उदाहरण तैयार किया जाता है या f2फिर f3इसे लागू किया जाता है, जबकि हमेशा के f1लिए ऐसा ही होता Function1[Int, Int]है।
रान्डेल शुल्ज

@RandallSchulz ने कहा कि वैल संस्करण को नए फ़ंक्शन उदाहरण की आवश्यकता नहीं है, इस मामले में कभी भी डीफ़ का उपयोग क्यों किया जाएगा?
virtualeyes

2
@virtualeyes केवल वही स्थिति जिसे मैं याद कर सकता हूं कि जहां कोई डीफिल्टिंग फंक्शनन देखता है [...] मान कॉम्बिनेटर पार्सर लाइब्रेरी में है। यह उन विधियों को लिखने के लिए बहुत सामान्य नहीं है जो उपज का कार्य करती हैं और वस्तुतः कभी भी किसी को एक शब्द का उपयोग एक शब्दार्थ / कार्यात्मक रूप से अपरिवर्तनीय फ़ंक्शन की कई प्रतियों को प्राप्त करने के लिए नहीं किया जाता है।
रान्डेल शुल्ज

जवाबों:


112

f1 एक फ़ंक्शन है जो पूर्णांक लेता है और पूर्णांक देता है।

f2शून्य एरीट के साथ एक विधि है जो एक फ़ंक्शन देता है जो पूर्णांक लेता है और एक पूर्णांक देता है। (जब आप f2बाद में REPL पर टाइप करते हैं , तो यह विधि के लिए एक कॉल बन जाता है f2।)

f3रूप में ही है f2। आप वहां टाइप इंट्रेंस को नियोजित नहीं कर रहे हैं।


6
क्यों f1एक है functionऔर f2एक है method?
Freewind

17
@Freewind, एक फंक्शन एक ऑब्जेक्ट है जिसका नाम विधि है apply। एक विधि, ठीक है, एक विधि है।
लापताफैक्टर

बहुत बढ़िया जवाब। प्रश्न: आप कहते हैं कि F2 में शून्य एरीटी है, लेकिन क्या यह एकात्मक नहीं है? en.wikipedia.org/wiki/Arity "एक अशक्त कार्य कोई तर्क नहीं लेता है। एक अपरिपक्व कार्य एक तर्क लेता है।" बस उत्सुक!
मैथ्यू कॉर्नेल

5
@MatthewCornell, f2स्वयं कोई तर्क स्वीकार नहीं करता है। फ़ंक्शन ऑब्जेक्ट जो इसे लौटाता है।
लापताफैक्टर

122

एक वर्ग के अंदर, valमूल्यांकन पर मूल्यांकन किया जाता है , जबकि defकेवल जब मूल्यांकन किया जाता है, और हर बार , फ़ंक्शन को कहा जाता है। नीचे दिए गए कोड में आप देखेंगे कि x का मूल्यांकन पहली बार किया गया है जब ऑब्जेक्ट का उपयोग किया गया है, लेकिन फिर से नहीं जब एक्स सदस्य तक पहुंच हो। इसके विपरीत, y का मूल्यांकन तब नहीं किया जाता है जब ऑब्जेक्ट को त्वरित किया जाता है, लेकिन हर बार सदस्य तक पहुंचने के दौरान इसका मूल्यांकन किया जाता है।

  class A(a: Int) {
    val x = { println("x is set to something"); a }
    def y = { println("y is set to something"); a }
  }

  // Prints: x is set to something
  val a = new A(1)

  // Prints: "1"
  println(a.x)

  // Prints: "1"                               
  println(a.x)

  // Prints: "y is set to something" and "1"                                  
  println(a.y)

  // Prints: "y is set to something" and "1"                                                                                   
  println(a.y)

@JacobusR क्या केवल एक वर्ग के अंदर ही सही है?
एंड्रयू कासिडी 16

उदाहरण के लिए: scala> var b = 5 b: Int = 5 scala> val a: (Int => Int) = x => x + ba: Int => Int = <function1> scala> a (5) res48: Int = १० स्काला> बी = ६ बी: इंट = ६ स्काला> ए (५) रेस ४ ९: इंट = ११ मैं उम्मीद कर रहा था कि एक (५) १० को लौटा देगा और बी के मूल्य को इनलाइन कर दिया गया है
एंड्रयू कैसिडी

@AndrewCassidy फ़ंक्शन aअपरिवर्तनीय है और प्रारंभिक मूल्यांकन पर मूल्यांकन किया गया है, लेकिन bएक परिवर्तनशील मूल्य बना हुआ है। तो संदर्भ को bआरंभीकरण के दौरान सेट किया गया है, लेकिन इसके द्वारा संग्रहित मूल्य bपरस्पर बना रहता है। मनोरंजन के लिए अब आप एक नया निर्माण कर सकते हैं val b = 123। इसके बाद आपका a(5)हमेशा 11 देगा, क्योंकि bयह अब पूरी तरह से नया मूल्य है।
जैक

@JacobusR धन्यवाद ... यह समझ में आता है। यह "लेक्सिकल स्कोप" की परिभाषा से मेल खाता है क्योंकि फ़ंक्शन मूल "var b" का संदर्भ देता है। मुझे लगता है कि जो मुझे भ्रमित करता है वह यह है कि कहते हैं: var b = 5; वैल सी = बी; बी = 6; अलग तरह से काम करता है। मुझे लगता है कि मुझे एक फ़ंक्शन परिभाषा की उम्मीद नहीं करनी चाहिए जो मूल "लेक्सिकल" गुंजाइश के संदर्भ में एक ही तरीके से व्यवहार करने के लिए वहन करती है।
एंड्रयू कैसिडी

3

Def x = e जैसी परिभाषा को निष्पादित करने से अभिव्यक्ति e का मूल्यांकन नहीं होगा । इसके बजाय का मूल्यांकन किया जाता है जब भी x का उपयोग किया जाता है। वैकल्पिक रूप से, स्काला एक मूल्य परिभाषा प्रदान करता है वैल एक्स = ई , करता है जो दाएँ हाथ की ओर का मूल्यांकन परिभाषा के मूल्यांकन के भाग के रूप। यदि बाद में एक्स का उपयोग किया जाता है, तो इसे तुरंत के पूर्व-गणना मूल्य से बदल दिया जाता है , ताकि अभिव्यक्ति का फिर से मूल्यांकन करने की आवश्यकता न हो।

मार्टिन ओडस्की द्वारा स्केला बाय उदाहरण

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.