What are all the uses of an underscore in Scala?

后端 未结 7 1333
南笙
南笙 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: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.

提交回复
热议问题