स्काला पहचानकर्ता "अंतर्निहित" क्या है?


169

मैंने implicitlyस्काला के उदाहरणों में प्रयुक्त एक फ़ंक्शन देखा है । यह क्या है, और इसे कैसे प्रयोग किया जाता है?

यहाँ उदाहरण :

scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
     |                         implicit def stringImpl = new Foo[String] {
     |                             def apply(list : List[String]) = println("String")
     |                         }
     |                         implicit def intImpl = new Foo[Int] {
     |                             def apply(list : List[Int]) =  println("Int")
     |                         }
     |                     } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit

scala> foo(1)
<console>:8: error: type mismatch;
 found   : Int(1)
 required: List[?]
       foo(1)
           ^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:8: error: could not find implicit value for evidence parameter of type
 Foo[Double]
       foo(List(1.0))
          ^

ध्यान दें कि हमें लिखना है implicitly[Foo[A]].apply(x)क्योंकि कंपाइलर सोचता है implicitly[Foo[A]](x)इसका मतलब है कि हम implicitlyमापदंडों के साथ कॉल करते हैं।

यह भी देखें कि वस्तुओं / प्रकारों आदि की जांच कैसे करें। स्काला आरईपीएल से? और स्काला इंपीटिट्स के लिए कहाँ दिखता है?

जवाबों:


206

यहाँ कुछ सरल तरीके का उपयोग करने के कुछ कारण दिए गए हैं implicitly

समझने के लिए / Implicit Views का निवारण करें

जब चयन का उपसर्ग (उदाहरण के लिए विचार करें, the.prefix.selection(args)इसमें एक सदस्य शामिल नहीं होता है , तब भी selectionलागू किया जा argsसकता है args) वर्तमान या संलग्न स्कोप्स में, विरासत में मिला, या आयात किया गया, जो कि या तो उस प्रकार के कार्य हैं जो परिभाषित, या समकक्ष निहित विधियों के the.prefixसाथ एक प्रकार के हैं selection

scala> 1.min(2) // Int doesn't have min defined, where did that come from?                                   
res21: Int = 1

scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>

scala> res22(1) // 
res23: AnyRef{def min(i: Int): Int} = 1

scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt

जब कोई अभिव्यक्ति एक्सपेक्टेड टाइप के अनुरूप न हो तो इम्प्लिमेंट व्यू को भी ट्रिगर किया जा सकता है:

scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1

यहाँ संकलक इस समारोह के लिए लग रहा है:

scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>

एक प्रसंग सीमा द्वारा प्रस्तुत इंप्लिमेंट पैरामीटर तक पहुँचना

Implicit Views की तुलना में Implicit पैरामीटर स्कैला की एक अधिक महत्वपूर्ण विशेषता है। वे टाइप क्लास पैटर्न का समर्थन करते हैं। मानक पुस्तकालय कुछ स्थानों पर इसका उपयोग करता है - देखें scala.Orderingऔर इसका उपयोग कैसे किया जाता है SeqLike#sorted। Array मेनिफ़ेस्ट और CanBuildFromउदाहरणों को पास करने के लिए Implicit Parameters का भी उपयोग किया जाता है ।

स्कैला 2.8, निहित मापदंडों के लिए एक शॉर्टहैंड सिंटैक्स की अनुमति देता है, जिसे संदर्भ सीमा कहा जाता है। संक्षेप में, एक प्रकार के पैरामीटर के साथ एक विधि जिसके Aलिए एक अंतर्निहित पैरामीटर की आवश्यकता होती है M[A]:

def foo[A](implicit ma: M[A])

के रूप में फिर से लिखा जा सकता है:

def foo[A: M]

लेकिन निहित पैरामीटर पारित करने का क्या मतलब है, लेकिन इसका नामकरण नहीं है? विधि को लागू करते समय यह कैसे उपयोगी हो सकता है foo?

अक्सर, निहित पैरामीटर को सीधे संदर्भित करने की आवश्यकता नहीं होती है, इसे अंतर्निहित तर्क के रूप में एक अन्य विधि जिसे कहा जाता है, के माध्यम से सुरंगित किया जाएगा। यदि यह आवश्यक है, तो आप अभी भी संदर्भ बाउंड के साथ terse विधि हस्ताक्षर को बनाए रख सकते हैं, और implicitlyमूल्य को भौतिक बनाने के लिए कॉल कर सकते हैं:

def foo[A: M] = {
   val ma = implicitly[M[A]]
}

स्पष्ट रूप से निहित मापदंडों का एक सबसेट पास करना

मान लीजिए कि आप एक ऐसी विधि कह रहे हैं जो एक व्यक्ति को टाइप क्लास आधारित दृष्टिकोण का उपयोग करके प्रिंट करता है:

trait Show[T] { def show(t: T): String }
object Show {
  implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
  implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }

  def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}

case class Person(name: String, age: Int)
object Person {
  implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
    def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
  }
}

val p = Person("bob", 25)
implicitly[Show[Person]].show(p)

क्या होगा अगर हम उस तरीके को बदलना चाहते हैं जो नाम आउटपुट है? हम स्पष्ट रूप से कॉल कर सकते हैं PersonShow, स्पष्ट रूप से एक विकल्प पास कर सकते हैं Show[String], लेकिन हम चाहते हैं कि कंपाइलर पास हो Show[Int]

Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)

2
scala> 1.min (2) res0: Int = 1 Scala 2.10.3 में मुझे एक त्रुटि मिलती है: scala> implicitly [int => {def min (i: Int): Any}] <कंसोल>: 8: त्रुटि: Int => AnyRef {def min (i: Int): किसी भी} से कोई निहित दृश्य उपलब्ध नहीं है। निहितार्थ [Int => {def min (i: Int): कोई भी}]
jhegedus

यह उत्तर नवीनतम संस्करण के लिए अपडेट किया जाएगा।
एमेट

1
संक्षेप में [Int => AnyVal {def min (i: Int): Int}] काम करेगा। जवाब में तय किया जाना चाहिए।
मल्कावियानो

211

Implicitlyस्केला 2.8 में उपलब्ध है और इसे पूर्वनिर्धारित के रूप में परिभाषित किया गया है:

def implicitly[T](implicit e: T): T = e

यह आमतौर पर यह जांचने केT लिए उपयोग किया जाता है कि क्या प्रकार का निहित मूल्य उपलब्ध है और यदि ऐसा है तो इसे वापस कर दें।

रिट्रोनियम की प्रस्तुति से सरल उदाहरण :

scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
       val c = implicitly[Int]
                         ^

6
विधि बिल्कुल जाँच नहीं करता है; ऐसा लगता है कि यदि कोई अंतर्निहित मान उपलब्ध नहीं है, और यदि वहाँ है, तो उसे संकलित करने के लिए एक संकलित त्रुटि होती है। क्या आप इस बारे में कुछ और संदर्भ प्रदान कर सकते हैं कि मैं इसका उपयोग क्यों करना चाहता हूं?
davetron5000

17
implicitly[Ordering[(Int, String)]].compare( (1, "b"), (1, "a") ), विशेष रूप से एक प्रसंग def foo[A: Ordering](a1: A, a2: A) = implicitly[Ordering[A]].compare(a1, a2)
बन्ध

1
ऊपर दिए गए वीडियो लिंक में रेट्रोइन की चर्चा देखने के लिए, बिंदु 13:50 पर जाएं।
chaotic3quilibrium

-2

"फिश टू यू टू फिश" उत्तर स्कैल्पॉक नाइटलाइफ़ में वर्तमान में उपलब्ध अल्फाबेटिक सदस्य इंडेक्स का उपयोग करना है । #पैकेज / वर्ग फलक के शीर्ष पर अक्षर (और , गैर-वर्णनात्मक नाम के लिए) उस अक्षर से शुरू होने वाले सदस्य नामों के सूचकांक के लिए लिंक होते हैं (सभी वर्गों में)। यदि आप चुनते हैं I, उदाहरण के लिए, आपको implicitlyएक घटना के साथ प्रविष्टि मिलेगी Predef, जिसमें आप वहां दिए गए लिंक से जा सकते हैं।


46
बेशक, उन स्कैलडोक के बारे में कुछ भी स्पष्ट रूप से नहीं कहा गया है, ताकि शायद ही दस्तावेज के रूप में गिना जाए। कोई यह कैसे पता लगाएगा कि वह विधि अकेले उन डॉक्स से क्या करती है? मुझे लगता है कि नियमित रूप से स्काला प्रलेखन द्वारा नीचा दिखाया गया है। अव्यवस्थित रूप से तरीकों का व्यवहार स्पष्ट से बहुत दूर है, और उन पर प्रलेखन मुश्किल से कोई नहीं से बेहतर है। स्टैक ओवरफ्लो के लिए भगवान का शुक्र है। / अंत शेख़ी
जेफ


4
प्रकार हस्ताक्षर दस्तावेजों यह एक बहुत अच्छी तरह से।
रेट्रो 11

21
implicitस्काला में एक महत्वपूर्ण भाषा-सुविधा प्रतीत होती है, और निश्चित रूप से उचित स्पष्टीकरण के योग्य है। यह सोचकर कि डॉक्स केवल एक टाइप-सिग्नेचर काउंट का विवरण वास्तविक उत्तर की तुलना में बौद्धिक आत्म-संतुष्टि की तरह लगता है। ओपी द्वारा पूछे गए विशिष्ट प्रश्नों को देखें - यह क्या है, और इसका उपयोग कैसे किया जाता है? न तो इसके द्वारा उत्तर दिया गया, न ही रात के डॉक्स में, जिसे आप एक वास्तविक लिंक भी प्रदान नहीं करते हैं। scala-lang.org/files/archive/nightly/docs/library/… यह कुछ भी नहीं सिखाता है। वास्तविक डॉक्स के उदाहरणों के लिए निकलस विर्थ या टर्बो पास्कल देखें। -1
थॉमस डब्ल्यू

3
implicitऔर implicitlyसंबंधित हैं, लेकिन काफी अलग हैं। implicitकीवर्ड भाषा का हिस्सा है। implicitlyमानक पुस्तकालय में सादे स्काला कोड में परिभाषित किया गया है। चूंकि ऑन-लाइन डॉक्स में स्रोत लिंक शामिल हैं, मेरा मानना ​​है कि उन दस्तावेज़ों और लिंक किए गए स्रोत के लिए प्रश्नकर्ता को संदर्भित करना अभी भी सबसे अच्छा है।
रान्डेल शुल्ज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.