Scala 做爲一門函數式編程語言,對習慣了指令式編程語言的同窗來講,會不大習慣,這裏除了思惟方式以外,還有語法層面的,好比 underscore(下劃線)就會出如今多種場合,令初學者至關疑惑,今天就來總結下 Scala 中下劃線的用法。java
一、存在性類型: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") } 五、通配模式:Wildcard patterns Some(5) match { case Some(_) => println("Yes") } 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 _ => } val (a, _) = (1, 2) for (_ <- 1 to 10) 六、通配導入:Wildcard imports import java.util._ 七、隱藏導入:Hiding imports // 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 => _ , _ } 八、鏈接字母和標點符號:Joining letters to punctuation def bang_!(x: Int) = 5 九、佔位符語法:Placeholder syntax List(1, 2, 3) map (_ + 2) _ + _ ( (_: Int) + (_: Int) )(2,3) val nums = List(1,2,3,4,5,6,7,8,9,10) nums map (_ + 2) nums sortWith(_>_) nums filter (_ % 2 == 0) nums reduceLeft(_+_) nums reduce (_ + _) nums reduceLeft(_ max _) nums.exists(_ > 5) nums.takeWhile(_ < 8) 十、偏應用函數:Partially applied functions def fun = { // Some code } val funLike = fun _ List(1, 2, 3) foreach println _ 1 to 5 map (10 * _) //List("foo", "bar", "baz").map(_.toUpperCase()) List("foo", "bar", "baz").map(n => n.toUpperCase()) 十一、初始化默認值:default value var i: Int = _ 十二、做爲參數名: //訪問map var m3 = Map((1,100), (2,200)) for(e<-m3) println(e._1 + ": " + e._2) m3 filter (e=>e._1>1) m3 filterKeys (_>1) m3.map(e=>(e._1*10, e._2)) m3 map (e=>e._2) //訪問元組:tuple getters (1,2)._2 1三、參數序列:parameters Sequence _*做爲一個總體,告訴編譯器你但願將某個參數看成參數序列處理。例如val s = sum(1 to 5:_*)就是將1 to 5看成參數序列處理。 //Range轉換爲List List(1 to 5:_*) //Range轉換爲Vector Vector(1 to 5: _*) //可變參數中 def capitalizeAll(args: String*) = { args.map { arg => arg.capitalize } } val arr = Array("what's", "up", "doc?") capitalizeAll(arr: _*)
這裏須要注意的是,如下兩種寫法實現的是徹底不同的功能:編程
foo _ // Eta expansion of method into method value foo(_) // Partial function application
Example showing why foo(_) and foo _ are different:api
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).app
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.函數式編程
Refer:函數
[1] What are all the uses of an underscore in Scala?ui
http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scalaspa
[2] Scala punctuation (AKA symbols and operators)scala
[3] Scala中的下劃線到底有多少種應用場景?
http://www.zhihu.com/question/21622725
[4] Strange type mismatch when using member access instead of extractor
[5] Scala簡明教程
http://colobu.com/2015/01/14/Scala-Quick-Start-for-Java-Programmers/
[6] Scala入門到精通——第二十三節 高級類型 (二)