What are all the uses of an underscore in Scala?
Asked Answered
A

7

611

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. Explanatory examples are appreciated.

Andras answered 3/11, 2011 at 19:43 Comment(1)
I read this decent set of slides not long ago: Scala Dreaded UnderscoreSaw
W
646

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.

Wolfort answered 3/11, 2011 at 19:58 Comment(12)
I think there are two or three that all fit under underscore usage in pattern matching, but +1 for joining letters to punctuation! :-)Marplot
@Wolfort I don't think println _ is a partially applied function. It is another example of placeholder syntax right? Meaning map(_ + 2) expands to something similar to map(x => x + 2) just as pritnln(_) expands to something similar to map(x => println(x))Soothsay
@AndrewCassidy Actually println _ and println(_) are different. You can see this for example in that they handle existential and polymorphic types slightly differently. Will come up with an example in a bit.Wolfort
@AndrewCassidy OK I have added an example.Wolfort
Ive documented some formal language theory motivations for underscore and tried to show the links of each use with something in Natural Language here https://mcmap.net/q/65474/-motivation-for-scala-underscore-in-terms-of-formal-language-theory-and-good-styleRafat
@GiovanniBotta, I guess it should be var x: Any = _Garrik
So underscore is basically Scala's wildcard?Mittel
@Mittel It's like a wildcard that stands for many different kinds of wildness. A wild wildcard, if you will.Wolfort
lol this language is so trippy... Why does an electrical engineer need to know such a high level language like scala though?Mittel
val _ = 5 looks really strange.Cameron
I think you forget the one to gives a Seq[T] as Seq.size parameters, Map(Seq((1, 1), (2, 2), (3, 3)):_*), don t remember the exact name at the moment. Thanks for your sharing, i’ve still many things to learn !Subshrub
I'd upvote this answer if each case would have an equal alternative of what it means.Duhl
M
209

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.

Marplot answered 3/11, 2011 at 20:4 Comment(11)
May be you can add var i: Int = _ or the special case of pattern matching val (a, _) = (1, 2) or the special case of discarded val for (_ <- 1 to 10) doIt()Infirm
And def f: T; def f_=(t: T) combo for creating mutable f member.Infirm
Pattern matching is already covered, and _ on method names is cheating. But, well, ok. I just hope someone else updates the FAQ... :-)Marplot
Maybe you miss this one. vertx.newHttpServer.websocketHandler(_.writeXml(html))Farley
@Farley That's anonymous function placeholder parameter, fifth down the list.Marplot
@yarek-t The for (_ <- 1 to 10) is not discarded parameter, because _ is not in the place of a parameter, but of a pattern match. Well, I suppose it could be argued that in the absence of a pattern, it's just a parameter, so it could be thought of like that as well.Marplot
@DanielC.Sobral Apoligies. I saw it as a for comprehension, but of course its not a flatMap. _ is so overloaded, it trips me up regularlyCyzicus
@YarekT It can be flatmap, map or foreach, but that's not the point. You can do stuff like this: for ((a,b) <- listOfPairs) yield a+b, and that becomes listOfPairs.map { case (a,b) => a + b }, which is why I classified it as pattern matching instead of ignored parameter.Marplot
You are right, it is a pattern match underneath, sort of counter-intuitive as practically you don't have that parameter to use. (could x@_ <- ... be valid here?) For comprehensions also can use =: for { ...; _ = foo()}, which throws me off, Thats a proper discarded value isn't it.Cyzicus
@YarekT x@_ <- ...? Maybe you meant x @ _*? I think _* can only be used inside unapplySeq matchers. As for the second, no, because assignment is also a pattern match. You can do val Some(a) = someOption, for example.Marplot
I think explanatory code examples with results of commands would be usefulEleanor
B
96

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 _
}
Bladdernose answered 3/11, 2011 at 19:47 Comment(3)
That is a good explanation, but it doesn't even have all of them. It's missing ignored parameters/variables, joining letters and punctuation, existential types, higher kinded typesWolfort
in your List(1,2,3,4,5).foreach(print(_)) it's much more readable to just do List(1,2,3,4,5).foreach(print), you don't even really need the underscore at all, but I guess that's just a matter of styleMagnific
how about "_" works as place holder in Collections with function .map, .flatten, .toList ...... Sometime, it makes me misunderstanding. :(Guerin
M
37

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())
Magnific answered 10/4, 2014 at 7:11 Comment(3)
so _ here acts as a namespace of all available functions?Missymist
@Crt no, it acts as a shorthand for n => nMagnific
isn't this the placeholder syntax mentioned in the top two answers?Cynde
C
15

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)

Chevy answered 13/11, 2014 at 16:48 Comment(0)
N
14

Besides the usages that JAiro mentioned, I like this one:

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

If someone needs all connection properties, he can do:

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

If you need just a host and a port, you can do:

val ( host, port, _, _ ) = getConnectionProps
Nardi answered 3/11, 2011 at 19:52 Comment(0)
E
2

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 ”

Ebert answered 17/1, 2018 at 10:0 Comment(1)
feel everyone's example is an element of iteration, I think this is more like a low-level syntax sugar, said lambda concise conversionEbert

© 2022 - 2024 — McMap. All rights reserved.