导入模块包

在 Scala 导入模块包时,_ 的作用类似于 Java 导入模块包时的 *。

  1. // 引入 matching 包中的所有类
  2. import scala.util.matching._
  3. // 引入对象 Fun 中的所有成员(相当于 Java 中的 static import)
  4. import com.test.Fun._
  5. // 引入对象 Fun 中的所有成员,但将 `Foo` 改名为 `Bar`(相当于 Python 中的 `import Foo from com.test.Fun as Bar`)
  6. import com.test.Fun.{ Foo => Bar , _ }
  7. // imports all the members except Foo. To exclude a member rename it to _
  8. // 引入对象 Fun 中的所有成员,但通过将 `Foo` 改名为 `_` 而忽略。
  9. import com.test.Fun.{ Foo => _ , _ }

模式匹配

Scala 中的模式匹配和 C/C++ 或者 Java 中的 switch - case 语句类似。在 Scala 中的模式匹配中,下划线 是匹配任意内容的通配符。最基本的用法时, 相当于 C/C++ 中的 default。

  1. import scala.util.Random
  2. val x: Int = Random.nextInt(10)
  3. x match {
  4. case 0 => "zero"
  5. case 1 => "one"
  6. case 2 => "two"
  7. case _ => "other"
  8. }

更高阶的用法中,_ 可以嵌套使用,这时候就远超出 default case 的作用了。

  1. expr match {
  2. case List(1, _, _) => " a list with three element and the first element is 1 "
  3. case List(_*) => " a list with zero or more elements "
  4. case Map[_, _] => " matches a map with any key type and any value type "
  5. case _ => " others "
  6. }

匿名函数的参数

Scala 和 Python、C++ 等语言一样,也有匿名函数的设定。
下划线 可用作是匿名函数的参数的占位符,但对于每一个参数,只能用下划线占位一次。
例如,在 Scala 中 2 *
相当于 Python 中的 lambda x: 2 x 或者 C++ 中的 { return 2 x; };
但对于 Python 中的 lambda x: x x 不能写成 Scala 中的 _ ——因为在 Scala 中, * 表示匿名函数接受 2 个参数,函数返回值是两个参数的乘积。又例如,下列 Scala 代码中的 print() 相当于 x => print(x):
List(1, 2, 3, 4, 5).foreach(print())
下列 Scala 代码中的
+ 相当于 (x, y) => x + y:
List(1, 2, 3, 4, 5).reduceLeft(
+ _)

阻止函数意外调用

众所周知,Scala 是函数式语言。在 Scala 中,函数是一等公民,和普通变量一样可以赋值。
但由于在 Scala 中函数调用时可省略括号,如果你打算将一个函数赋值给一个新的变量,则函数可能会被意外地调用而后将函数的返回值赋值。这种时候,我们需要在函数名之后加上 _ 来阻止函数调用——类似 TeX 中的 \relax 阻止继续执行的作用。

  1. class Test {
  2. def foo = {
  3. // some code
  4. }
  5. val bar = foo _
  6. }