স্কালায় আন্ডারস্কোরের সমস্ত ব্যবহার কী?


539

আমি কটাক্ষপাত গ্রহণ করেছি তালিকা গ্রহণ সার্ভে 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 _

ডিফল্ট আরম্ভকারী izer

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(_)একটি ল্যাম্বডা হয়; কোনও সুস্পষ্ট আর্গুমেন্ট প্রকার ছাড়াই ল্যাম্বদা লেখার সময়, স্কালা foreachপ্রত্যাশিত যুক্তি থেকে প্রকারটি অনুমান করে এবং _ => Unit এটি একটি প্রকার (যেখানে কেবল সরল _নয়), তাই এটি প্রতিস্থাপন এবং অনুমান করা যায়।

আমি যে স্কেলার মুখোমুখি হয়েছিলাম এটি সম্ভবত সবচেয়ে জটিল কৌশল।

নোট করুন যে এই উদাহরণটি 2.13 এ সংকলিত হয়েছে। এটি আন্ডারস্কোর হিসাবে নির্ধারিত ছিল যেমন এটি উপেক্ষা করুন।


4
আমার মনে হয় এমন দুটি বা তিনটি রয়েছে যা সমস্ত প্যাটার্ন মিলের ক্ষেত্রে আন্ডারস্কোর ব্যবহারের অধীনে ফিট করে তবে বিরামচিহ্নগুলিতে চিঠিগুলিতে যোগদানের জন্য +1! :-)
ড্যানিয়েল সি সোব্রাল


2
@ তবে আমি মনে করি না যে প্রিন্টলন _ একটি আংশিক প্রয়োগিত ফাংশন। এটি ঠিক স্থানধারক সিনট্যাক্সের অন্য একটি উদাহরণ? অর্থ ম্যাপ (_ + 2) মানচিত্রের অনুরূপ কিছুতে প্রসারিত (x => x + 2) ঠিক যেমন pritnln (_) মানচিত্রের অনুরূপ কিছুতে প্রসারিত (x => প্রিন্টলন (এক্স))
অ্যান্ড্রু ক্যাসিডি

7
@ অ্যান্ড্রুক্যাসিডি প্রকৃতপক্ষে println _এবং println(_)পৃথক। আপনি এটি উদাহরণস্বরূপ দেখতে পাচ্ছেন যে তারা অস্তিত্ব ও পলিমারফিক ধরণের কিছুটা আলাদাভাবে পরিচালনা করে। কিছুটা উদাহরণ নিয়ে হাজির হবে।
ওয়েন

3
@ অ্যান্ড্রুস্যাসিডি ঠিক আছে আমি একটি উদাহরণ যুক্ত করেছি।
ওয়েন

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()
ভালের

1
এবং def f: T; def f_=(t: T)মিউটেবল এফ সদস্য তৈরির জন্য কম্বো।
huynhjl

প্যাটার্ন মিলটি ইতিমধ্যে কভার করা হয়েছে, এবং _পদ্ধতিতে নাম প্রতারণা করছে। তবে, ঠিক আছে, ঠিক আছে। আমি কেবল আশা করি যে অন্য কেউ FAQ আপডেট করেছে ... :-)
ড্যানিয়েল সি সোব্রাল

1
হতে পারে আপনি এই এক মিস। উল্লম্ব.নাইএইচটিপিএস সার্ভার. ওয়েবসকেট হ্যান্ডলার (_। লিখনএক্সএমএল (এইচটিএমএল))
অ্যাঞ্জেলোখ

@ অ্যাংলোখ এটি অনামী ফাংশন স্থানধারক পরামিতি, তালিকার পঞ্চম নীচে।
ড্যানিয়েল সি সোব্রাল

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)

আপনি যদি কোনও নতুন ভেরিয়েবলের জন্য কোনও ফাংশন নির্ধারণের চেষ্টা করেন তবে ফাংশনটি শুরু করা হবে এবং ফলাফলটি ভেরিয়েবলের জন্য বরাদ্দ করা হবে। পদ্ধতির প্রার্থনার জন্য alচ্ছিক বন্ধনীগুলির কারণে এই বিভ্রান্তি ঘটে। এটি অন্য ভেরিয়েবলে নির্ধারণের জন্য আমাদের ফাংশন নামের পরে _ ব্যবহার করা উচিত।

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

2
এটি একটি ভাল ব্যাখ্যা, তবে এটির সবগুলিও নেই। এটা তোলে উপেক্ষিত পরামিতি / ভেরিয়েবল, যোগদান অক্ষর এবং যতিচিহ্ন থাকতে পারে, অস্তিত্ববাদের ধরনের, উচ্চতর kinded ধরনের অনুপস্থিত
ওয়েন

আপনার মধ্যে List(1,2,3,4,5).foreach(print(_))এটি কেবল আরও পাঠযোগ্য List(1,2,3,4,5).foreach(print), আপনার এমনকি এমনকি আন্ডারস্কোরের আদৌ প্রয়োজন নেই, তবে আমার ধারণা এটি কেবল স্টাইলের বিষয়
বৈদ্যুতিন কফি

1
ফাংশন। ম্যাপ, .ফ্লেটেন, টোলিস্ট ...... সহ কোনও সময়ে "_" কীভাবে সংগ্রহে স্থানধারক হিসাবে কাজ করে তা আমাকে ভুল বোঝাবুঝি করে তোলে। :(
m0z4rt

34

এখানে একটি ব্যবহার রয়েছে যা আমি দেখতে পাচ্ছি এখানে উপস্থিত সবাই তালিকার জন্য ভুলে গেছে বলে মনে হচ্ছে ...

বরং এটি করা:

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

আপনি কেবল এটি করতে পারেন:

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

সুতরাং _ এখানে সমস্ত উপলব্ধ ফাংশনগুলির নামস্থান হিসাবে কাজ করে?
Crt

2
কোন @Crt, এটির জন্য একটি সাধারণভাবে সংক্ষেপে হিসাবে কাজ করেn => n
ইলেকট্রিক কফি

2
এটি কি শীর্ষস্থানীয় দুটি উত্তরে উল্লিখিত স্থানধারক সিনট্যাক্স নয়?
জোয়েলব

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" তে রূপান্তরিত হবে


প্রত্যেকের উদাহরণটি পুনরাবৃত্তির একটি উপাদান হিসাবে অনুভব করুন, আমি মনে করি এটি আরও নিম্ন-স্তরের সিনট্যাক্স চিনির মতো, ল্যাম্বডা সংক্ষিপ্ত রূপান্তরটি বলেছেন
কে.স্টেভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.