स्काला में लागू फ़ंक्शन क्या है?


311

मैंने इसे कभी नहीं सोचा था कि आकस्मिक असम्बद्धता और क्रियावाचक संज्ञाओं में (एक AddTwoवर्ग में एक और भी है apply) उदाहरण।

मैं समझता हूं कि यह वाक्यगत शर्करा है, इसलिए (मैं संदर्भ से घटा) यह कुछ कोड को अधिक सहज बनाने के लिए डिज़ाइन किया गया है।

एक applyफ़ंक्शन के साथ एक वर्ग क्या अर्थ देता है? इसका उपयोग किस लिए किया जाता है, और यह किन उद्देश्यों के लिए कोड को बेहतर बनाता है (अनमैर्षलिंग, क्रिया संज्ञा आदि)?

साथी ऑब्जेक्ट में उपयोग करने पर यह कैसे मदद करता है?


4
यहां तक ​​कि एक त्वरित googling कई अच्छे लेख लाता है। यहाँ एक है: jackcoughonsoftware.blogspot.com/2009/01/…
om-nom-nom-


6
वास्तव में यह जावा / सी ++ में एक कंस्ट्रक्टर के रूप में ही है, लेकिन मूल्य वापस कर सकता है और
ses

यह एक विधि है, एक फ़ंक्शन नहीं है। स्काला में तरीकों और कार्यों के बीच अंतर बहुत महत्वपूर्ण है।
राइटफोल्ड

1
Zoidberg पर विस्तार से बता दें "तरीके सिर्फ कार्यों उस वर्ग के राज्य का उपयोग कर सकते हैं" twitter.github.io/scala_school/basics.html सामान्य तौर पर इस स्काला की तुलना में अधिक के लिए लागू होता stackoverflow.com/questions/155609/...
DharmaTurtle

जवाबों:


640

गणितज्ञों के अपने छोटे मज़ेदार तरीके होते हैं, इसलिए कहने के बजाय "हम fइसे फ़ंक्शन xको एक पैरामीटर के रूप में कहते हैं" जैसा कि हम प्रोग्रामर कहेंगे, वे " fअपने तर्क पर फ़ंक्शन लागू करने" के बारे में बात करते हैं x

गणित और कंप्यूटर विज्ञान में, लागू एक फ़ंक्शन है जो कार्यों को तर्कों पर लागू करता है।
विकिपीडिया

applyस्काला में ऑब्जेक्ट ओरिएंटेड और फंक्शनल प्रतिमानों के बीच अंतर को बंद करने के उद्देश्य से कार्य करता है। स्काला में प्रत्येक फ़ंक्शन को एक ऑब्जेक्ट के रूप में दर्शाया जा सकता है। प्रत्येक फ़ंक्शन का एक OO प्रकार भी होता है: उदाहरण के लिए, एक फ़ंक्शन जो Intपैरामीटर लेता है और एक IntOO प्रकार का होता है Function1[Int,Int]

 // define a function in scala
 (x:Int) => x + 1

 // assign an object representing the function to a variable
 val f = (x:Int) => x + 1

चूंकि सब कुछ स्काला में एक वस्तु है, fअब इसे Function1[Int,Int]ऑब्जेक्ट के संदर्भ के रूप में माना जा सकता है । उदाहरण के लिए, हम toStringइनहेरिट की गई विधि को कॉल कर सकते हैं Any, जो कि शुद्ध फ़ंक्शन के लिए असंभव होगा, क्योंकि फ़ंक्शन में विधियाँ नहीं हैं:

  f.toString

या हम किसी अन्य Function1[Int,Int]ऑब्जेक्ट को कॉल composeविधि पर परिभाषित कर सकते हैं और fदो अलग-अलग कार्यों को एक साथ कर सकते हैं:

 val f2 = f.compose((x:Int) => x - 1)

अब अगर हम वास्तव में फ़ंक्शन को निष्पादित करना चाहते हैं, या जैसा कि गणितज्ञ कहते हैं, "इसके तर्कों पर एक फ़ंक्शन लागू करें" हम ऑब्जेक्ट applyपर विधि को कॉल करेंगे Function1[Int,Int]:

 f2.apply(2)

लेखन f.apply(args)हर बार जब आप एक समारोह एक वस्तु के रूप में प्रतिनिधित्व पर अमल करना चाहते हैं वस्तु उन्मुख रास्ता है, लेकिन ज्यादा अतिरिक्त जानकारी के जोड़े बिना कोड के लिए अव्यवस्था का एक बहुत जोड़ना होगा और यह अच्छा होगा इस तरह के, अधिक मानक संकेतन का उपयोग करने में सक्षम हो के रूप में f(args)। यही कारण है कि जब भी स्काला संकलक में कदम रखता है और जब भी हमारे पास fफ़ंक्शन ऑब्जेक्ट का संदर्भ f (args)होता है और प्रतिनिधित्व फ़ंक्शन को तर्क लागू करने के लिए लिखता है तो कंपाइलर चुपचाप f (args)ऑब्जेक्ट विधि कॉल में फैलता है f.apply (args)

स्काला में प्रत्येक फ़ंक्शन को एक ऑब्जेक्ट के रूप में माना जा सकता है और यह दूसरे तरीके से भी काम करता है - प्रत्येक ऑब्जेक्ट को एक फ़ंक्शन के रूप में माना जा सकता है, बशर्ते इसकी applyविधि हो। फ़ंक्शन नोटेशन में ऐसी वस्तुओं का उपयोग किया जा सकता है:

// we will be able to use this object as a function, as well as an object
object Foo {
  var y = 5
  def apply (x: Int) = x + y
}


Foo (1) // using Foo object in function notation 

ऐसे कई उपयोग मामले हैं जब हम किसी वस्तु को एक फ़ंक्शन के रूप में मानना ​​चाहेंगे। सबसे आम परिदृश्य एक कारखाना पैटर्न है । फ़ैक्टरी विधि का उपयोग करके कोड में अव्यवस्था जोड़ने के बजाय, हम applyसंबद्ध वर्ग का एक नया उदाहरण बनाने के लिए तर्कों के एक सेट पर आपत्ति कर सकते हैं :

List(1,2,3) // same as List.apply(1,2,3) but less clutter, functional notation

// the way the factory method invocation would have looked
// in other languages with OO notation - needless clutter
List.instanceOf(1,2,3) 

इसलिए applyविधि स्कैला में कार्यों और वस्तुओं के बीच की खाई को बंद करने का एक आसान तरीका है।


1
आप किसी ऑब्जेक्ट में कस्टम चर प्रकार कैसे जोड़ सकते हैं। AFAIK यह संभव नहीं है। यहाँ एक उदाहरण है: आपके पास यह वर्ग है class Average[YType](yZeroValue:YType)। जब आप ऑब्जेक्ट्स को टाइप params नहीं ले सकते, तो आप इसे YType से कैसे पास करेंगे?
एड्रियन

स्काला के प्रकार आमतौर पर तर्कों के आधार पर अनुमान लगाए जा सकते हैं, लेकिन यदि आप उन्हें वर्ग कोष्ठक के माध्यम से आपूर्ति नहीं कर सकते हैं। इसलिए जब आप एक औसत वस्तु को तुरंत कहते हैं, तो आप "वेल एवीजी = नया औसत [इंट] (0)" कह सकते हैं
एंजेलो जेनोविस

4
मामले की कक्षाएं यहाँ एक उल्लेख के लायक हैं। केस क्लासेस आसानी से, स्वचालित रूप से और अदृश्य रूप से जोड़ता है applyऔर unapplyक्लास के एक साथी ऑब्जेक्ट (अन्य चीजों के बीच) के तरीके। तो इस तरह सिर्फ एक लाइन के साथ एक क्लास को परिभाषित case class Car(make:String, model: String, year: Short, color: String)करना कार क्लास की नई वस्तुओं को बस द्वारा उत्पादन करना संभव बनाता है val myCar = Car("VW","Golf",1999,"Blue"):। इसके लिए शॉर्टहैंड हैCar.apply(...)
Kjetil S.

1
every object can be treated as a function, provided it has the apply method- इतना अब समझ में आता है।
अरज


51

यह इस विचार से आता है कि आप अक्सर किसी वस्तु पर कुछ लगाना चाहते हैं । अधिक सटीक उदाहरण कारखानों में से एक है। जब आपके पास एक कारखाना होता है, तो आप ऑब्जेक्ट बनाने के लिए उस पर पैरामीटर लागू करना चाहते हैं ।

स्काला के लोगों ने सोचा कि, जैसा कि कई परिस्थितियों में होता है, कॉल करने के लिए शॉर्टकट रखना अच्छा हो सकता है apply। इस प्रकार जब आप किसी ऑब्जेक्ट को सीधे पैरामीटर देते हैं, तो यह इस तरह से डिग जाता है जैसे कि आप इन पैरामीटर्स को उस ऑब्जेक्ट के लागू फ़ंक्शन में पास करते हैं:

class MyAdder(x: Int) {
  def apply(y: Int) = x + y
}

val adder = new MyAdder(2)
val result = adder(4) // equivalent to x.apply(4)

यह अक्सर साथी वस्तु में उपयोग होता है, एक वर्ग या एक विशेषता के लिए एक अच्छा कारखाना विधि प्रदान करने के लिए, यहाँ एक उदाहरण है:

trait A {
  val x: Int
  def myComplexStrategy: Int
}

object A {
  def apply(x: Int): A = new MyA(x)

  private class MyA(val x: Int) extends A {
    val myComplexStrategy = 42
  }
}

स्काला स्टैंडर्ड लाइब्रेरी से, आप देख सकते हैं कि कैसे scala.collection.Seqलागू किया जाता है: Seqएक विशेषता है, इस प्रकार new Seq(1, 2)संकलन नहीं होगा लेकिन साथी ऑब्जेक्ट के लिए धन्यवाद और आवेदन करें, आप कॉल कर सकते हैं Seq(1, 2)और कार्यान्वयन को साथी ऑब्जेक्ट द्वारा चुना जाता है।


क्या इम्प्लिसिट के साथ ही आवेदन के समतुल्य को पूरा किया जा सकता है?
jayunit100

11

यहां उन लोगों के लिए एक छोटा सा उदाहरण है जो जल्दी से नाश करना चाहते हैं

 object ApplyExample01 extends App {


  class Greeter1(var message: String) {
    println("A greeter-1 is being instantiated with message " + message)


  }

  class Greeter2 {


    def apply(message: String) = {
      println("A greeter-2 is being instantiated with message " + message)
    }
  }

  val g1: Greeter1 = new Greeter1("hello")
  val g2: Greeter2 = new Greeter2()

  g2("world")


} 

उत्पादन

संदेश अभिवादन के साथ एक अभिवादन -1 का त्वरित मूल्यांकन किया जा रहा है

संदेश की दुनिया के साथ एक अभिवादन -2 का त्वरित मूल्यांकन किया जा रहा है


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