What are all the uses of an underscore in Scala?

后端 未结 7 1153
南笙
南笙 2020-11-21 07:24

I\'ve taken a look at the list of surveys taken on scala-lang.org and noticed a curious question: \"Can you name all the uses of “_”?\". Can you? If yes, please do so here.

相关标签:
7条回答
  • 2020-11-21 07:28

    From (my entry) in the FAQ, which I certainly do not guarantee to be complete (I added two entries just two days ago):

    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+)
    

    This is also part of this question.

    0 讨论(0)
  • 2020-11-21 07:29

    The ones I can think of are

    Existential types

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

    Higher kinded type parameters

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

    Ignored variables

    val _ = 5
    

    Ignored parameters

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

    Ignored names of self types

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

    Wildcard patterns

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

    Wildcard patterns in interpolations

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

    Sequence wildcard in patterns

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

    Wildcard imports

    import java.util._
    

    Hiding imports

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

    Joining letters to operators

    def bang_!(x: Int) = 5
    

    Assignment operators

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

    Placeholder syntax

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

    Method values

    List(1, 2, 3) foreach println _
    

    Converting call-by-name parameters to functions

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

    Default initializer

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

    There may be others I have forgotten!


    Example showing why foo(_) and foo _ are different:

    This example comes from 0__:

    trait PlaceholderExample {
      def process[A](f: A => Unit)
    
      val set: Set[_ => Unit]
    
      set.foreach(process _) // Error 
      set.foreach(process(_)) // No Error
    }
    

    In the first case, process _ represents a method; Scala takes the polymorphic method and attempts to make it monomorphic by filling in the type parameter, but realizes that there is no type that can be filled in for A that will give the type (_ => Unit) => ? (Existential _ is not a type).

    In the second case, process(_) is a lambda; when writing a lambda with no explicit argument type, Scala infers the type from the argument that foreach expects, and _ => Unit is a type (whereas just plain _ isn't), so it can be substituted and inferred.

    This may well be the trickiest gotcha in Scala I have ever encountered.

    Note that this example compiles in 2.13. Ignore it like it was assigned to underscore.

    0 讨论(0)
  • 2020-11-21 07:38

    There is one usage I can see everyone here seems to have forgotten to list...

    Rather than doing this:

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

    You could can simply do this:

    List("foo", "bar", "baz").map(_.toUpperCase())
    
    0 讨论(0)
  • 2020-11-21 07:44

    Here are some more examples where _ is used:

    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)
    

    In all above examples one underscore represents an element in the list (for reduce the first underscore represents the accumulator)

    0 讨论(0)
  • 2020-11-21 07:48

    An excellent explanation of the uses of the underscore is Scala _ [underscore] magic.

    Examples:

     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))
    

    In Scala, _ acts similar to * in Java while importing packages.

    // 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 => _ , _ }
    

    In Scala, a getter and setter will be implicitly defined for all non-private vars in a object. The getter name is same as the variable name and _= is added for the setter name.

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

    Usage:

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

    If you try to assign a function to a new variable, the function will be invoked and the result will be assigned to the variable. This confusion occurs due to the optional braces for method invocation. We should use _ after the function name to assign it to another variable.

    class Test {
        def fun = {
            // Some code
        }
        val funLike = fun _
    }
    
    0 讨论(0)
  • 2020-11-21 07:49

    There is a specific example that "_" be used:

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

    may be equal to :

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

    Applying “_” in some scenarios will automatically convert to “(x$n) => x$n ”

    0 讨论(0)
提交回复
热议问题