स्काला में अंडरस्कोर के सभी उपयोग क्या हैं?


540

मैंने scala-lang.org पर किए गए सर्वेक्षणों की सूची पर एक नज़र डाली है और एक जिज्ञासु प्रश्न देखा है: " क्या आप" _ "के सभी उपयोगों का नाम दे सकते हैं? "। क्या आप? यदि हाँ, तो कृपया यहाँ करें। व्याख्यात्मक उदाहरणों की सराहना की जाती है।


15
मैं स्लाइड्स के इस सभ्य सेट को बहुत पहले नहीं पढ़ता: स्काला ड्रेडेड अंडरस्कोर
डैन बर्टन

जवाबों:


576

मैं जिनके बारे में सोच सकता हूं

अस्तित्व के प्रकार

def foo(l: List[Option[_]]) = ...

उच्च प्रकार के प्रकार के पैरामीटर

case class A[K[_],T](a: K[T])

उपेक्षित चर

val _ = 5

मापदंडों की अनदेखी की

List(1, 2, 3) foreach { _ => println("Hi") }

स्वयं प्रकारों के नामों की अनदेखी

trait MySeq { _: Seq[_] => }

वाइल्डकार्ड पैटर्न

Some(5) match { case Some(_) => println("Yes") }

प्रक्षेपों में वाइल्डकार्ड पैटर्न

"abc" match { case s"a$_c" => }

पैटर्न में अनुक्रम वाइल्डकार्ड

C(1, 2, 3) match { case C(vs @ _*) => vs.foreach(f(_)) }

वाइल्डकार्ड आयात

import java.util._

आयात छिपाना

import java.util.{ArrayList => _, _}

ऑपरेटरों को पत्र जोड़ना

def bang_!(x: Int) = 5

असाइनमेंट ऑपरेटर

def foo_=(x: Int) { ... }

प्लेसहोल्डर सिंटेक्स

List(1, 2, 3) map (_ + 2)

विधि मान

List(1, 2, 3) foreach println _

कार्यों के लिए कॉल-बाय-नेम पैरामीटर परिवर्तित करना

def toFunction(callByName: => Int): () => Int = callByName _

डिफ़ॉल्ट इनिशियलाइज़र

var x: String = _   // unloved syntax may be eliminated

कुछ और भी हो सकते हैं जिन्हें मैं भूल गया हूँ!


उदाहरण दिखा रहा है कि क्यों foo(_)और foo _अलग हैं:

यह उदाहरण 0__ से आता है :

trait PlaceholderExample {
  def process[A](f: A => Unit)

  val set: Set[_ => Unit]

  set.foreach(process _) // Error 
  set.foreach(process(_)) // No Error
}

पहले मामले में, process _एक विधि का प्रतिनिधित्व करता है; स्काला पॉलीमॉर्फिक विधि लेता है और टाइप पैरामीटर में भरकर इसे मोनोमोर्फिक बनाने का प्रयास करता है, लेकिन यह महसूस करता है कि ऐसा कोई प्रकार नहीं है जिसे इसके लिए भरा जा सके, Aजो टाइप देगा (_ => Unit) => ?(एक्सिस्टेशनल _एक प्रकार नहीं है)।

दूसरे मामले में, process(_)एक मेमना है; जब कोई स्पष्ट तर्क प्रकार के साथ एक लैम्ब्डा लेखन, स्काला तर्क से प्रकार infers कि foreachउम्मीद है, और _ => Unit है एक प्रकार (जबकि सिर्फ सादा _नहीं है), तो यह प्रतिस्थापित और निष्कर्ष निकाला जा सकता।

यह अच्छी तरह से Scala मैं कभी सामना करना पड़ा है में सबसे मुश्किल हो सकता है।

ध्यान दें कि यह उदाहरण 2.13 में संकलित है। इसे अनदेखा करें जैसे इसे अंडरस्कोर को सौंपा गया था।


4
मुझे लगता है कि दो या तीन हैं जो सभी पैटर्न मिलान में अंडरस्कोर उपयोग के तहत फिट होते हैं, लेकिन विराम चिह्नों में शामिल होने के लिए +1! :-)
डैनियल सी। सोबरल


2
@ मुझे नहीं लगता कि println _ एक आंशिक रूप से लागू फ़ंक्शन है। यह प्लेसहोल्डर सिंटैक्स का एक और उदाहरण है? मतलब नक्शा (_ + 2) कुछ इसी तरह के नक्शे (x => x + 2) से मिलता-जुलता है, जैसे कि pritnln (_) नक्शा (x => println (x)) के समान है
एंड्रयू कासिडी

7
@AndrewCassidy असल में println _और println(_)अलग हैं। आप इसे उदाहरण के लिए देख सकते हैं कि वे अस्तित्वगत और बहुरूपी प्रकारों को थोड़ा अलग तरीके से संभालते हैं। एक उदाहरण के साथ थोड़ा सा सामने आएगा।
ओवेन

3
@AndrewCassidy ठीक है मैंने एक उदाहरण जोड़ा है।
ओवेन

179

FAQ में (मेरी प्रविष्टि) से , जिसे मैं निश्चित रूप से पूरा होने की गारंटी नहीं देता (मैंने दो दिन पहले दो प्रविष्टियाँ जोड़ीं):

import scala._    // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]]       // Higher kinded type parameter
def f(m: M[_])    // Existential type
_ + _             // Anonymous function placeholder parameter
m _               // Eta expansion of method into method value
m(_)              // Partial function application
_ => 5            // Discarded parameter
case _ =>         // Wild card pattern -- matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10)  // same thing
f(xs: _*)         // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _    // Initialization to the default value
def abc_<>!       // An underscore must separate alphanumerics from symbols on identifiers
t._2              // Part of a method name, such as tuple getters
1_000_000         // Numeric literal separator (Scala 2.13+)

यह भी इस सवाल का हिस्सा है ।


2
हो सकता है कि आप जोड़ सकते हैं var i: Int = _या पैटर्न मिलान val (a, _) = (1, 2)के विशेष मामले या खारिज किए गए वैल के विशेष मामलेfor (_ <- 1 to 10) doIt()
huynhjl

1
और def f: T; def f_=(t: T)परस्पर एफ सदस्य बनाने के लिए कॉम्बो।
हुहुंजल

पैटर्न मिलान पहले से ही कवर किया गया है, और _विधि नामों पर धोखा है। लेकिन, ठीक है, ठीक है। मुझे उम्मीद है कि किसी और ने FAQ ... :-)
डैनियल सी। सोबरल

1
शायद आपको यह याद आती है। vertx.newHttpServer.websocketHandler (_। writeXml (html))
angelokh

@angelok वह अनाम फ़ंक्शन प्लेसहोल्डर पैरामीटर है, जो सूची से पांचवें स्थान पर है।
डैनियल सी। सोबरल

84

अंडरस्कोर के उपयोग का एक उत्कृष्ट विवरण स्कैला _ [अंडरस्कोर] जादू है

उदाहरण:

 def matchTest(x: Int): String = x match {
     case 1 => "one"
     case 2 => "two"
     case _ => "anything other than one and two"
 }

 expr match {
     case List(1,_,_) => " a list with three element and the first element is 1"
     case List(_*)  => " a list with zero or more elements "
     case Map[_,_] => " matches a map with any key type and any value type "
     case _ =>
 }

 List(1,2,3,4,5).foreach(print(_))
 // Doing the same without underscore: 
 List(1,2,3,4,5).foreach( a => print(a))

स्काला में, पैकेज आयात करते समय जावा के _समान कार्य करता *है।

// Imports all the classes in the package matching
import scala.util.matching._

// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._

// Imports all the members of the object Fun but renames Foo to Bar
import com.test.Fun.{ Foo => Bar , _ }

// Imports all the members except Foo. To exclude a member rename it to _
import com.test.Fun.{ Foo => _ , _ }

स्काला में, एक गेट्टर और सेटर को एक वस्तु में सभी गैर-निजी संस्करणों के लिए स्पष्ट रूप से परिभाषित किया जाएगा। गेट्टर नाम चर नाम के समान है और _=सेटर नाम के लिए जोड़ा जाता है।

class Test {
    private var a = 0
    def age = a
    def age_=(n:Int) = {
            require(n>0)
            a = n
    }
}

उपयोग:

val t = new Test
t.age = 5
println(t.age)

यदि आप किसी फ़ंक्शन को नए चर में असाइन करने का प्रयास करते हैं, तो फ़ंक्शन को लागू किया जाएगा और परिणाम को चर को सौंपा जाएगा। यह भ्रम विधि आमंत्रण के लिए वैकल्पिक ब्रेसिज़ के कारण होता है। हमें फ़ंक्शन नाम के बाद इसे दूसरे चर पर असाइन करने के लिए _ का उपयोग करना चाहिए।

class Test {
    def fun = {
        // Some code
    }
    val funLike = fun _
}

2
यह एक अच्छा विवरण है, लेकिन यह भी उन सभी को नहीं है। यह अनदेखा पैरामीटर / चर गायब है, अक्षर और विराम चिह्न, अस्तित्व के प्रकार, उच्च प्रकार के प्रकार
Owen

आपके लिए List(1,2,3,4,5).foreach(print(_))यह सिर्फ पढ़ने के लिए बहुत अधिक योग्य है List(1,2,3,4,5).foreach(print), आपको वास्तव में अंडरस्कोर की बिल्कुल भी आवश्यकता नहीं है, लेकिन मुझे लगता है कि यह सिर्फ स्टाइल की बात है
इलेक्ट्रिक कॉफी

1
कैसे के बारे में "_" फ़ंक्शन .map, .flatten, .toList ...... के साथ संग्रह में स्थान धारक के रूप में काम करता है ...... कभी-कभी, यह मुझे गलतफहमी देता है। :(
m0z4rt

34

एक उपयोग है जिसे मैं यहां देख सकता हूं कि सभी लोग सूची को भूल गए हैं ...

ऐसा करने के बजाय:

List("foo", "bar", "baz").map(n => n.toUpperCase())

आप बस यह कर सकते हैं:

List("foo", "bar", "baz").map(_.toUpperCase())

तो _ यहाँ सभी उपलब्ध कार्यों के नाम स्थान के रूप में कार्य करता है?
Crt

2
कोई @Crt, इसके लिए एक आशुलिपि के रूप में कार्य करता हैn => n
इलेक्ट्रिक कॉफी

2
क्या यह शीर्ष दो उत्तरों में उल्लिखित प्लेसहोल्डर सिंटैक्स नहीं है?
18

13

यहां कुछ और उदाहरण दिए गए हैं जहां _इसका उपयोग किया जाता है:

val nums = List(1,2,3,4,5,6,7,8,9,10)

nums filter (_ % 2 == 0)

nums reduce (_ + _)

nums.exists(_ > 5)

nums.takeWhile(_ < 8)

उपरोक्त सभी उदाहरणों में एक अंडरस्कोर सूची में एक तत्व का प्रतिनिधित्व करता है (पहले अंडरस्कोर को कम करने के लिए संचायक का प्रतिनिधित्व करता है)


11

इसके अलावा प्रयोगों कि जेरो उल्लेख किया है, मैं यह पसंद:

def getConnectionProps = {
    ( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}

यदि किसी को सभी कनेक्शन संपत्तियों की आवश्यकता है, तो वह कर सकता है:

val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps

यदि आपको सिर्फ एक मेजबान और एक बंदरगाह की आवश्यकता है, तो आप कर सकते हैं:

val ( host, port, _, _ ) = getConnectionProps

0

एक विशिष्ट उदाहरण है कि "_" का उपयोग किया जाता है:

  type StringMatcher = String => (String => Boolean)

  def starts: StringMatcher = (prefix:String) => _ startsWith prefix

इसके बराबर हो सकता है:

  def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix

"_" को कुछ परिदृश्यों में लागू करने से स्वचालित रूप से "(x $ n) => x $ n" में परिवर्तित हो जाएगा


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