原文鏈接:https://my.oschina.net/leejun2005/blog/405305
Scala 作為一門函數(shù)式編程語言,對習(xí)慣了指令式編程語言的同學(xué)來說,會(huì)不大習(xí)慣击狮,這里除了思維方式之外,還有語法層面的,比如 underscore(下劃線)就會(huì)出現(xiàn)在多種場合段磨,令初學(xué)者相當(dāng)疑惑,今天就來總結(jié)下 Scala 中下劃線的用法耗绿。
1苹支、存在性類型:Existential types
def foo(l: List[Option[_]]) = ...
2、高階類型參數(shù):Higher kinded type parameters
case class A[K[_],T](a: K[T])
3误阻、臨時(shí)變量:Ignored variables
val _ = 5
4债蜜、臨時(shí)參數(shù):Ignored parameters
List(1, 2, 3) foreach { _ => println("Hi") }
5晴埂、通配模式: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)
6、通配導(dǎo)入:Wildcard imports
import java.util._
7寻定、隱藏導(dǎo)入: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 => _ , _ }
8儒洛、連接字母和標(biāo)點(diǎn)符號:Joining letters to punctuation
def bang_!(x: Int) = 5
9、占位符語法: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)
10狼速、偏應(yīng)用函數(shù):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())
11琅锻、初始化默認(rèn)值:default value
var i: Int = _
12、作為參數(shù)名:
//訪問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
13向胡、參數(shù)序列:parameters Sequence
_*作為一個(gè)整體恼蓬,告訴編譯器你希望將某個(gè)參數(shù)當(dāng)作參數(shù)序列處理。例如val s = sum(1 to 5:_*)就是將1 to 5當(dāng)作參數(shù)序列處理僵芹。
//Range轉(zhuǎn)換為List
List(1 to 5:_*)
//Range轉(zhuǎn)換為Vector
Vector(1 to 5: _*)
//可變參數(shù)中
def capitalizeAll(args: String*) = {
args.map { arg =>
arg.capitalize
}
}
val arr = Array("what's", "up", "doc?")
capitalizeAll(arr: _*)
這里需要注意的是处硬,以下兩種寫法實(shí)現(xiàn)的是完全不一樣的功能:
foo _ // Eta expansion of method into method value
foo(_) // Partial function application
Example showing why foo(_) and foo _ are different:
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.
Refer:
[1] What are all the uses of an underscore in Scala?
http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala
[2] Scala punctuation (AKA symbols and operators)
[3] Scala中的下劃線到底有多少種應(yīng)用場景?
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入門到精通——第二十三節(jié) 高級類型 (二)