Sunday 20 September 2009
Understanding the _ (underscore) in Scala
By Maxime Biais, Sunday 20 September 2009 at 17:27 :: Scala
I started to learn Scala. I started by reading some code snippets and then write my own program. Scala integrates features of object-oriented and functional languages. When reading code example I saw that a reserved keyword was often used, it's the Scala wildcard: the underscore (_). And it's used in different ways.
Underscore and anonymous parameters
I read some examples that use the Scala wildcard character: _ (the underscore). Here is one:
val sum = List(1, 2, 3).reduceLeft(_+_)
Note that the reduceLeft method apply a function of two arguments cumulatively to the items of the List. That means _+_ is a function of t two arguments. This example can be translated to:
val sum = List(1, 2, 3).reduceLeft((x, y) => x + y)
(x) => x is the Scala notation to write anonymous functions. For pythoners, this is the equivalent to lambda x: x.
As described in the Scala language specification. Implicit anonymous functions using underscores in parameter position. Some examples below. The expressions in the left column are each function values which expand to the anonymous functions on their right:
_ + 1 x => x + 1 _ * _ (x1, x2) => x1 * x2 (_: int) * 2 (x: int) => (x: int) * 2 if (_) x else y z => if (z) x else y _.map(f) x => x.map(f) _.map(_ + 1) x => x.map(y => y + 1)
Another example, I think, a bit harder to see where the anonymous function is hidden (note that foreach takes a function of one argument):
object Test extends Application { private def printAddition(a: Int, b: Int) { println(a + b) } List(1, 2, 3).foreach(printAddition(5, _)) }
is equivalent to:
object Test extends Application { private def printAddition(a: Int, b: Int) { println(a + b) } List(1, 2, 3).foreach((x) => printAddition(5, x)) }
Underscore and partially applied function
Let's write a simple function that return a function:
object Test extends Application { private def createAddFunc(a: Int) = { (x: Int) => a + x } val add100 = createAddFunc(100) // createAddFunc return a function, // so add100 references a function add100(3) // call add100 method (returns 100 + 3) // We can also write this: createAddFunc(100)(3) // Or affect createAddFunc to another name (note the trailing _) var createAddFuncCopy = createAddFunc _ }
In the last line of code of this example, the trailing underscore tells the compiler to look at createAddFunc as a functional, and not invoke it.
Underscore and pattern matching
Scala has a pattern matching mechanism (first-match policy). In this case, the underscore matches everything that has not be matched before:
object Test extends Application { private def cardColor(symbol: String) : String = symbol match { case "heart" => "red" case "diamond" => "red" case "spade" => "black" case "club" => "black" case _ => "typo ?" } println(cardColor("club")) println(cardColor("clubb")) }
prints:
black typo ?
In this case, the Scala underscore is the equivalent to the underscore in OCaml, it matches everything that has not be matched:
let cardColor = function
"heart" | "diamond" -> "red"
| "spade" | "club" -> "black"
| _ -> "typo ?";;
print_endline (cardColor "club");;
print_endline (cardColor "clubb");;
Note the previous Scala code can also be written à la OCaml using the "|" symbol:
private def cardColor(symbol: String) : String = symbol match { case "heart" | "diamond" => "red" case "spade" | "club" => "black" case _ => "typo ?" }
Underscore and package imports
Another use of the _ is to import all tje classes of a package:
import scala.io._
THe equivalent of the java syntax:
import java.util.*; 


