612

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.

erip
  • 16,374
  • 11
  • 66
  • 121
Ivan
  • 63,011
  • 101
  • 250
  • 382
  • 17
    I read this decent set of slides not long ago: [Scala Dreaded Underscore](http://www.slideshare.net/normation/scala-dreaded) – Dan Burton Nov 04 '11 at 01:07

7 Answers7

645

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.

som-snytt
  • 39,429
  • 2
  • 47
  • 129
Owen
  • 38,836
  • 14
  • 95
  • 125
  • 4
    I think there are two or three that all fit under underscore usage in pattern matching, but +1 for joining letters to punctuation! :-) – Daniel C. Sobral Nov 03 '11 at 20:06
  • 2
    @Owen 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)) – Andrew Cassidy Apr 09 '14 at 16:24
  • 8
    @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. – Owen Apr 09 '14 at 19:49
  • 4
    @AndrewCassidy OK I have added an example. – Owen May 04 '14 at 05:01
  • Ive documented some formal language theory motivations for underscore and tried to show the links of each use with something in Natural Language here http://stackoverflow.com/a/25763401/1586965 – samthebest Sep 11 '14 at 03:20
  • 2
    @GiovanniBotta, I guess it should be **var** x: Any = _ – srzhio Dec 11 '16 at 21:03
  • So underscore is basically Scala's wildcard? – shinzou Nov 13 '17 at 18:35
  • 1
    @shinzou It's like a wildcard that stands for many different kinds of wildness. A wild wildcard, if you will. – Owen Nov 14 '17 at 19:56
  • lol this language is so trippy... Why does an electrical engineer need to know such a high level language like scala though? – shinzou Nov 14 '17 at 22:34
  • `val _ = 5` looks really strange. – ziggystar Feb 02 '18 at 21:33
  • 1
    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 ! – KyBe Apr 21 '18 at 02:38
  • I'd upvote this answer if each case would have an equal alternative of what it means. – Nikolas Charalambidis Feb 05 '21 at 13:51
210

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.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • 2
    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()` – huynhjl Nov 04 '11 at 00:59
  • 1
    And `def f: T; def f_=(t: T)` combo for creating mutable f member. – huynhjl Nov 04 '11 at 01:06
  • Pattern matching is already covered, and `_` on method names is cheating. But, well, ok. I just hope someone else updates the FAQ... :-) – Daniel C. Sobral Nov 04 '11 at 02:31
  • 1
    Maybe you miss this one. vertx.newHttpServer.websocketHandler(_.writeXml(html)) – angelokh Aug 31 '13 at 06:05
  • @angelokh That's anonymous function placeholder parameter, fifth down the list. – Daniel C. Sobral Sep 02 '13 at 22:22
  • @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. – Daniel C. Sobral Jul 09 '19 at 20:35
  • @DanielC.Sobral Apoligies. I saw it as a for comprehension, but of course its not a flatMap. `_` is so overloaded, it trips me up regularly – Yarek T Jul 11 '19 at 08:50
  • @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. – Daniel C. Sobral Jul 11 '19 at 16:31
  • 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. – Yarek T Jul 11 '19 at 17:23
  • @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. – Daniel C. Sobral Jul 11 '19 at 19:05
  • I think explanatory code examples with results of commands would be useful – Dmitry Gonchar Aug 11 '22 at 05:07
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 _
}
Adowrath
  • 701
  • 11
  • 24
JAiro
  • 5,914
  • 2
  • 22
  • 21
  • 2
    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 types – Owen Nov 03 '11 at 19:50
  • 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 style – Electric Coffee Apr 10 '14 at 07:05
  • 1
    how about "_" works as place holder in Collections with function .map, .flatten, .toList ...... Sometime, it makes me misunderstanding. :( – m0z4rt Sep 21 '15 at 08:17
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())
Electric Coffee
  • 11,733
  • 9
  • 70
  • 131
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)

losty
  • 147
  • 1
  • 7
swaraj patil
  • 209
  • 2
  • 5
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
tolitius
  • 22,149
  • 6
  • 70
  • 81
1

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 ”

Ke.Steve
  • 39
  • 4
  • feel everyone's example is an element of iteration, I think this is more like a low-level syntax sugar, said lambda concise conversion – Ke.Steve Jan 17 '18 at 12:11