1. 程式人生 > >Scala Predef物件詳解

Scala Predef物件詳解

Scala Predef物件

目錄:

1.Predef原始碼

2.型別裝換

3.型別定義

4.條件檢查方法

5.輸入輸出方法

6.其他

1 Predef原始碼

為了方便起見,只要你編譯程式碼,Scala 編譯器就會自動匯入頂層Scala 包(名為scala)以及在java.lang 包(就像javac 的)中的定義。因此,許多常見的Java 和Scala 型別都可以不經過明顯地匯入或提供完整的名稱就可以使用。另外,編譯器還匯入了Predef 物件中的一些定。接下來,我們來詳細瞭解Predef 提供的特性。需要注意的是,Scala 2.11 版本的Predef 引入了很多變化,其中大部分是不可見的。

看一看原始碼:

package scala
object Predef extends scala.LowPriorityImplicits with scala.DeprecatedPredef {
  def classOf[T] : Predef.Class[T] = { /* compiled code */ }
  type Class[T] = java.lang.Class[T]
  type String = java.lang.String
  type Function[-A, +B] = scala.Function1[A, B]
  type Map[A, +B] = scala.collection.immutable.Map[A, B]
  type Set[A] = scala.collection.immutable.Set[A]
  val Map : scala.collection.immutable.Map.type = { /* compiled code */ }
  val Set : scala.collection.immutable.Set.type = { /* compiled code */ }
  @scala.deprecated("use `scala.reflect.ClassTag` instead", "2.10.0")
  @scala.annotation.implicitNotFound("No ClassManifest available for ${T}.")
  type ClassManifest[T] = scala.reflect.ClassManifest[T]
  type OptManifest[T] = scala.reflect.OptManifest[T]
  @scala.annotation.implicitNotFound("No Manifest available for ${T}.")
  type Manifest[T] = scala.reflect.Manifest[T]
  @scala.deprecated("use `scala.reflect.ClassTag` instead", "2.10.0")
  val ClassManifest : scala.reflect.ClassManifestFactory.type = { /* compiled code */ }
  val Manifest : scala.reflect.ManifestFactory.type = { /* compiled code */ }
  val NoManifest : scala.reflect.NoManifest.type = { /* compiled code */ }
  def manifest[T](implicit m : Predef.Manifest[T]) : Predef.Manifest[T] = { /* compiled code */ }
  @scala.deprecated("use scala.reflect.classTag[T] instead", "2.10.0")
  def classManifest[T](implicit m : Predef.ClassManifest[T]) : Predef.ClassManifest[T] = { /* compiled code */ }
  def optManifest[T](implicit m : Predef.OptManifest[T]) : Predef.OptManifest[T] = { /* compiled code */ }
  @scala.inline
  def identity[A](x : A) : A = { /* compiled code */ }
  @scala.inline
  def implicitly[T](implicit e : T) : T = { /* compiled code */ }
  @scala.inline
  def locally[T](x : T) : T = { /* compiled code */ }
  @scala.annotation.elidable(2000)
  def assert(assertion : scala.Boolean) : scala.Unit = { /* compiled code */ }
  @scala.inline
  @scala.annotation.elidable(2000)
  final def assert(assertion : scala.Boolean, message : => scala.Any) : scala.Unit = { /* compiled code */ }
  @scala.annotation.elidable(2000)
  def assume(assumption : scala.Boolean) : scala.Unit = { /* compiled code */ }
  @scala.inline
  @scala.annotation.elidable(2000)
  final def assume(assumption : scala.Boolean, message : => scala.Any) : scala.Unit = { /* compiled code */ }
  def require(requirement : scala.Boolean) : scala.Unit = { /* compiled code */ }
  @scala.inline
  final def require(requirement : scala.Boolean, message : => scala.Any) : scala.Unit = { /* compiled code */ }
  def ??? : scala.Nothing = { /* compiled code */ }
  @scala.deprecated("use built-in tuple syntax or Tuple2 instead", "2.11.0")
  type Pair[+A, +B] = scala.Tuple2[A, B]
  @scala.deprecated("use built-in tuple syntax or Tuple2 instead", "2.11.0")
  object Pair extends scala.AnyRef {
    def apply[A, B](x : A, y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
    def unapply[A, B](x : scala.Tuple2[A, B]) : scala.Option[scala.Tuple2[A, B]] = { /* compiled code */ }
  }
  @scala.deprecated("use built-in tuple syntax or Tuple3 instead", "2.11.0")
  type Triple[+A, +B, +C] = scala.Tuple3[A, B, C]
  @scala.deprecated("use built-in tuple syntax or Tuple3 instead", "2.11.0")
  object Triple extends scala.AnyRef {
    def apply[A, B, C](x : A, y : B, z : C) : scala.Tuple3[A, B, C] = { /* compiled code */ }
    def unapply[A, B, C](x : scala.Tuple3[A, B, C]) : scala.Option[scala.Tuple3[A, B, C]] = { /* compiled code */ }
  }
  implicit final class ArrowAssoc[A](self : A) extends scala.AnyVal {
    @scala.inline
    def ->[B](y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
    def →[B](y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
  }
  implicit final class Ensuring[A](self : A) extends scala.AnyVal {
    def ensuring(cond : scala.Boolean) : A = { /* compiled code */ }
    def ensuring(cond : scala.Boolean, msg : => scala.Any) : A = { /* compiled code */ }
    def ensuring(cond : scala.Function1[A, scala.Boolean]) : A = { /* compiled code */ }
    def ensuring(cond : scala.Function1[A, scala.Boolean], msg : => scala.Any) : A = { /* compiled code */ }
  }
  implicit final class StringFormat[A](self : A) extends scala.AnyVal {
    @scala.inline
    def formatted(fmtstr : Predef.String) : Predef.String = { /* compiled code */ }
  }
  implicit final class any2stringadd[A](self : A) extends scala.AnyVal {
    def +(other : Predef.String) : Predef.String = { /* compiled code */ }
  }
  implicit final class RichException(self : scala.Throwable) extends scala.AnyVal {
    @scala.deprecated("use Throwable#getStackTrace", "2.11.0")
    def getStackTraceString : _root_.scala.Predef.String = { /* compiled code */ }
  }
  implicit final class SeqCharSequence(@scala.deprecated("will be made private", "2.12.0") val __sequenceOfChars : scala.collection.IndexedSeq[scala.Char]) extends java.lang.Object with java.lang.CharSequence {
    def length() : scala.Int = { /* compiled code */ }
    def charAt(index : scala.Int) : scala.Char = { /* compiled code */ }
    def subSequence(start : scala.Int, end : scala.Int) : java.lang.CharSequence = { /* compiled code */ }
    override def toString() : _root_.scala.Predef.String = { /* compiled code */ }
  }
  implicit final class ArrayCharSequence(@scala.deprecated("will be made private", "2.12.0") val __arrayOfChars : scala.Array[scala.Char]) extends java.lang.Object with java.lang.CharSequence {
    def length() : scala.Int = { /* compiled code */ }
    def charAt(index : scala.Int) : scala.Char = { /* compiled code */ }
    def subSequence(start : scala.Int, end : scala.Int) : java.lang.CharSequence = { /* compiled code */ }
    override def toString() : _root_.scala.Predef.String = { /* compiled code */ }
  }
  implicit val StringCanBuildFrom : scala.collection.generic.CanBuildFrom[Predef.String, scala.Char, Predef.String] = { /* compiled code */ }
  @scala.inline
  implicit def augmentString(x : Predef.String) : scala.collection.immutable.StringOps = { /* compiled code */ }
  @scala.inline
  implicit def unaugmentString(x : scala.collection.immutable.StringOps) : Predef.String = { /* compiled code */ }
  def print(x : scala.Any) : scala.Unit = { /* compiled code */ }
  def println() : scala.Unit = { /* compiled code */ }
  def println(x : scala.Any) : scala.Unit = { /* compiled code */ }
  def printf(text : Predef.String, xs : scala.Any*) : scala.Unit = { /* compiled code */ }
  implicit def tuple2ToZippedOps[T1, T2](x : scala.Tuple2[T1, T2]) : scala.runtime.Tuple2Zipped.Ops[T1, T2] = { /* compiled code */ }
  implicit def tuple3ToZippedOps[T1, T2, T3](x : scala.Tuple3[T1, T2, T3]) : scala.runtime.Tuple3Zipped.Ops[T1, T2, T3] = { /* compiled code */ }
  implicit def genericArrayOps[T](xs : scala.Array[T]) : scala.collection.mutable.ArrayOps[T] = { /* compiled code */ }
  implicit def booleanArrayOps(xs : scala.Array[scala.Boolean]) : scala.collection.mutable.ArrayOps.ofBoolean = { /* compiled code */ }
  implicit def byteArrayOps(xs : scala.Array[scala.Byte]) : scala.collection.mutable.ArrayOps.ofByte = { /* compiled code */ }
  implicit def charArrayOps(xs : scala.Array[scala.Char]) : scala.collection.mutable.ArrayOps.ofChar = { /* compiled code */ }
  implicit def doubleArrayOps(xs : scala.Array[scala.Double]) : scala.collection.mutable.ArrayOps.ofDouble = { /* compiled code */ }
  implicit def floatArrayOps(xs : scala.Array[scala.Float]) : scala.collection.mutable.ArrayOps.ofFloat = { /* compiled code */ }
  implicit def intArrayOps(xs : scala.Array[scala.Int]) : scala.collection.mutable.ArrayOps.ofInt = { /* compiled code */ }
  implicit def longArrayOps(xs : scala.Array[scala.Long]) : scala.collection.mutable.ArrayOps.ofLong = { /* compiled code */ }
  implicit def refArrayOps[T <: scala.AnyRef](xs : scala.Array[T]) : scala.collection.mutable.ArrayOps.ofRef[T] = { /* compiled code */ }
  implicit def shortArrayOps(xs : scala.Array[scala.Short]) : scala.collection.mutable.ArrayOps.ofShort = { /* compiled code */ }
  implicit def unitArrayOps(xs : scala.Array[scala.Unit]) : scala.collection.mutable.ArrayOps.ofUnit = { /* compiled code */ }
  implicit def byte2Byte(x : scala.Byte) : java.lang.Byte = { /* compiled code */ }
  implicit def short2Short(x : scala.Short) : java.lang.Short = { /* compiled code */ }
  implicit def char2Character(x : scala.Char) : java.lang.Character = { /* compiled code */ }
  implicit def int2Integer(x : scala.Int) : java.lang.Integer = { /* compiled code */ }
  implicit def long2Long(x : scala.Long) : java.lang.Long = { /* compiled code */ }
  implicit def float2Float(x : scala.Float) : java.lang.Float = { /* compiled code */ }
  implicit def double2Double(x : scala.Double) : java.lang.Double = { /* compiled code */ }
  implicit def boolean2Boolean(x : scala.Boolean) : java.lang.Boolean = { /* compiled code */ }
  implicit def Byte2byte(x : java.lang.Byte) : scala.Byte = { /* compiled code */ }
  implicit def Short2short(x : java.lang.Short) : scala.Short = { /* compiled code */ }
  implicit def Character2char(x : java.lang.Character) : scala.Char = { /* compiled code */ }
  implicit def Integer2int(x : java.lang.Integer) : scala.Int = { /* compiled code */ }
  implicit def Long2long(x : java.lang.Long) : scala.Long = { /* compiled code */ }
  implicit def Float2float(x : java.lang.Float) : scala.Float = { /* compiled code */ }
  implicit def Double2double(x : java.lang.Double) : scala.Double = { /* compiled code */ }
  implicit def Boolean2boolean(x : java.lang.Boolean) : scala.Boolean = { /* compiled code */ }
  @scala.annotation.implicitNotFound("Cannot prove that ${From} <:< ${To}.")
  sealed abstract class <:<[-From, +To]() extends scala.AnyRef with scala.Function1[From, To] with scala.Serializable {
    
  }
  implicit def $conforms[A] : Predef.<:<[A, A] = { /* compiled code */ }
  @scala.deprecated("use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
  def conforms[A] : Predef.<:<[A, A] = { /* compiled code */ }
  @scala.annotation.implicitNotFound("Cannot prove that ${From} =:= ${To}.")
  sealed abstract class =:=[From, To]() extends scala.AnyRef with scala.Function1[From, To] with scala.Serializable {
    
  }
  object =:= extends scala.AnyRef with scala.Serializable {
    implicit def tpEquals[A] : Predef.=:=[A, A] = { /* compiled code */ }
  }
  class DummyImplicit() extends scala.AnyRef {
  }
  object DummyImplicit extends scala.AnyRef {
    implicit def dummyImplicit : Predef.DummyImplicit = { /* compiled code */ }
  }
}

2 型別轉換

implicit def byte2Byte(x : scala.Byte) : java.lang.Byte = { /* compiled code */ }
  implicit def short2Short(x : scala.Short) : java.lang.Short = { /* compiled code */ }
  implicit def char2Character(x : scala.Char) : java.lang.Character = { /* compiled code */ }
  implicit def int2Integer(x : scala.Int) : java.lang.Integer = { /* compiled code */ }
  implicit def long2Long(x : scala.Long) : java.lang.Long = { /* compiled code */ }
  implicit def float2Float(x : scala.Float) : java.lang.Float = { /* compiled code */ }
  implicit def double2Double(x : scala.Double) : java.lang.Double = { /* compiled code */ }
  implicit def boolean2Boolean(x : scala.Boolean) : java.lang.Boolean = { /* compiled code */ }
  implicit def Byte2byte(x : java.lang.Byte) : scala.Byte = { /* compiled code */ }
  implicit def Short2short(x : java.lang.Short) : scala.Short = { /* compiled code */ }
  implicit def Character2char(x : java.lang.Character) : scala.Char = { /* compiled code */ }
  implicit def Integer2int(x : java.lang.Integer) : scala.Int = { /* compiled code */ }
  implicit def Long2long(x : java.lang.Long) : scala.Long = { /* compiled code */ }
  implicit def Float2float(x : java.lang.Float) : scala.Float = { /* compiled code */ }
  implicit def Double2double(x : java.lang.Double) : scala.Double = { /* compiled code */ }
  implicit def Boolean2boolean(x : java.lang.Boolean) : scala.Boolean = { /* compiled code */ }

3 型別定義

Predef 定義了若干的型別及類型別名。為了鼓勵使用不可變集合,Predef 為最常用的不可變集合定義了別名:

type Class[T] = java.lang.Class[T]
type String = java.lang.String
type Map[A, +B] = scala.collection.immutable.Map[A, B]
type Set[A] = scala.collection.immutable.Set[A]
type Function[-A, +B] = scala.Function1[A, B]
val Map : scala.collection.immutable.Map.type = { /* compiled code */ }
val Set : scala.collection.immutable.Set.type = { /* compiled code */ }

支援型別推斷的其他一些Predef 型別。

我們經常使用a -> b(或等價的a → b)這種寫法:

object Test {
  def main(args: Array[String]): Unit = {

    val a = (1, "one")
    val b = 1 -> "one"
    val c = 1 → "one"
    println(a) //輸出:(1,one)
    println(b) //輸出:(1,one)
    println(c) //輸出:(1,one)
    val map = Map("one" -> 1, "two" -> 2)
    println(map) //輸出:Map(one -> 1, two -> 2)
  }
}

事實上,Scala 根本不知道a -> b 意味著什麼,因此上述方法並非沒有意義。這種“字面量”格式實際上運用了方法-> 和一個特殊的Scala 特性——隱式轉換。通過運用隱式轉換,我們可以在任意兩種型別值之間插入函式->。與此同時,由於a -> b 並不是元組的字面量語法,因此Scala 必須通過某些方式將該表示式轉化為元組(a, b)。

很明顯,->之所以能用,就是因為我們已經把->方法定義好了,也就是 ArrowAssoc的->方法,原始碼如下

  implicit final class ArrowAssoc[A](self : A) extends scala.AnyVal {
    @scala.inline
    def ->[B](y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
    def →[B](y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
  }

在此只因關鍵字implicit起的作用,具體執行過程:

(1) 編譯器發現我們試圖對String 物件執行-> 方法(例如“ one” -> 1)。
(2) 由於String 未定義-> 方法,編譯器將檢查當前作用域中是否存在定義了該方法的隱式轉換。
(3) 編譯器發現了ArrowAssoc 類。
(4) 編譯器將建立ArrowAssoc 物件,並向其傳入one 字串。
(5) 之後,編譯器將解析表示式中的-> 1 部分程式碼,並確認了整個表示式的型別與Map.apply 方法的預期型別相吻合,即兩者均為pair 例項。

如果希望執行隱式轉換,那麼在宣告時必須使用implicit 關鍵字,能夠執行隱式轉換的無外乎兩類:構造方法中只接受單一引數的型別或者是隻接受單一引數的方法。

為了限定引數型別,Scala有了隱式證據<:<,在哪裡用到了呢?

package cn.com.tengen.test.obj

object Test {
  def main(args: Array[String]): Unit = {

    val map = Map("one" -> 1, "two" -> 2)
    println(map.toMap) //輸出:Map(one -> 1, two -> 2)

    val list1 = List((1,"aa"),(2,"bb"),(3,"cc"),(4,"dd"))
    println(list1.toMap) //Map(1 -> aa, 2 -> bb, 3 -> cc, 4 -> dd)

    val list2 = List(1,2,3,4)
    println(list2.toMap) //丟擲異常
  }
}
  @scala.annotation.implicitNotFound("Cannot prove that ${From} <:< ${To}.")
  sealed abstract class <:<[-From, +To]() extends scala.AnyRef with scala.Function1[From, To] with scala.Serializable {
    
  }
package scala.collection

trait TraversableOnce[+A] extends scala.Any with scala.collection.GenTraversableOnce[A] {
    ...
  def toMap[T, U](implicit ev: _root_.scala.Predef.<:<[A, scala.Tuple2[T, U]]): scala.collection.immutable.Map[T, U] = {
    /* compiled code */
  }
    ...
}

4 條件檢查方法

有時你希望斷言某條件為真,希望它“快速失敗”(尤其在測試時)。Predef 定義了許多有助於達到這個目的的方法。

• def assert(assertion: Boolean)
測試條件是否為真,如果不為真,丟擲java.lang.AssertionError 異常。
• def assert(assertion: Boolean, message: => Any)
類似前面的assert,但增加了一個可選引數,該引數將被轉為錯誤資訊字串。
• def assume(assertion: Boolean)
與assert 相同,但其表示當一段程式碼塊(如方法)正確時,條件才為真。
• def assume(assertion: Boolean, message: => Any)
類似前面的assume,但增加了一個可選引數,該引數將被轉為錯誤資訊字串。
• def require(requirement: Boolean)
與assume 相同,但根據Scaladoc,其含義是呼叫方是否滿足某些條件,也可以表示某個實現不能得出特定的結果。
• def require(requirement: Boolean, message: => Any)
類似前面的require,但增加了一個可選引數,該引數將被轉為錯誤資訊字串。

5 輸入輸出方法

Scala把資料列印到控制檯,這是我們經常做的操作,其實他也是Predef定義的。Predef 為我們提供了四種將字串列印到stdout 的形式。

  def print(x : scala.Any) : scala.Unit = { /* compiled code */ }
  def println() : scala.Unit = { /* compiled code */ }
  def println(x : scala.Any) : scala.Unit = { /* compiled code */ }
  def printf(text : Predef.String, xs : scala.Any*) : scala.Unit = { /* compiled code */ }

• def print(x: Any): Unit
將x 轉為字串,然後寫到標準輸出,結尾不會自動新增換行。
• def printf(format: String, xs: Any*): Unit
用format 和其他引數xs 對printf 風格的字串進行格式化,然後將結果寫到標準輸出,結尾不會自動新增換行。
• def println(x: Any): Unit
類似print,但結尾會自動新增換行。
• def println(): Unit
向標準輸出列印空行。

在老的版本中(2.12之前)Predef提供了相當多的輸入方法:

@scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readLine() : DeprecatedPredef.super[Predef/*scala.Predef*/].String = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readLine(text : DeprecatedPredef.super[Predef/*scala.Predef*/].String, args : scala.Any*) : _root_.scala.Predef.String = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readBoolean() : scala.Boolean = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readByte() : scala.Byte = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readShort() : scala.Short = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readChar() : scala.Char = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readInt() : scala.Int = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readLong() : scala.Long = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readFloat() : scala.Float = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readDouble() : scala.Double = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readf(format : DeprecatedPredef.super[Predef/*scala.Predef*/].String) : scala.List[scala.Any] = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readf1(format : DeprecatedPredef.super[Predef/*scala.Predef*/].String) : scala.Any = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readf2(format : DeprecatedPredef.super[Predef/*scala.Predef*/].String) : scala.Tuple2[scala.Any, scala.Any] = { /* compiled code */ }
  @scala.deprecated("use the method in `scala.io.StdIn`", "2.11.0")
  def readf3(format : DeprecatedPredef.super[Predef/*scala.Predef*/].String) : scala.Tuple3[scala.Any, scala.Any, scala.Any] = { /* compiled code */ }

• def readBoolean(): Boolean
從標準輸入的一個整行中讀取一個Boolean 值。
• def readByte(): Byte
從標準輸入的一個整行中讀取一個Byte 值。
• def readChar(): Char
從標準輸入的一個整行中讀取一個Char 值。
• def readDouble(): Double
從標準輸入的一個整行中讀取一個Double 值。
• def readFloat(): Float
從標準輸入的一個整行中讀取一個Float 值。
• def readInt(): Int
從標準輸入的一個整行中讀取一個Int 值。
• def readLine(text: String, args: Any*): String
向標準輸出中列印格式化的提示文字,並從標準輸入中讀取一整行字串。
• def readLine(): String
從標準輸入中讀取一整行字串。
• def readLong(): Long
從標準輸入的一個整行中讀取一個Long 值。
• def readShort(): Short
從標準輸入的一個整行中讀取一個Short 值。
• def readf(format: String): List[Any]
根據format 中的區分符號,從標準輸入中讀取格式化輸入。
• def readf1(format: String): Any
根據format 中的區分符號,從標準輸入中讀取格式化輸入。並根據format 的指定,返回提取的第一個值。

• def readf2(format: String): (Any, Any)
根據format 中的區分符號,從標準輸入中讀取格式化輸入。並根據format 的指定,返回提取的前兩個值。
• def readf3(format: String): (Any, Any, Any)
根據format 中的區分符號,從標準輸入中讀取格式化輸入。並根據format 的指定,返回提取的前三個值。

在輸入時也可以選擇Java的方式:

  val read:Scanner = new Scanner(System.in)
  val line = read.nextLine()
  val b = read.nextByte()
  val s = read.nextShort()
  val i = read.nextInt()
  val f = read.nextFloat()
  val d = read.nextDouble()
  val l = read.nextLong()
  val bool = read.nextBoolean()

6 雜項方法

1 ???

在一個尚未實現的方法的方法體中呼叫。它為方法提供了具體的定義,允許編譯器將方法所屬的型別視為具體(與抽象對應)的類。然而,如果呼叫該方法,就會丟擲scala.NotImplementedError 異常。原始碼如下:

def ??? : scala.Nothing = { /* compiled code */ }

2 identity

直接返回引數x。在將方法傳給組合器(combinator)時,如果不需要進行修改,就可以用它。例如:在一個工作流程中,我們通過給map 傳入一個函式來對集合元素進行轉化。有時我們不需要做任何轉化,你可以傳入identity。原始碼如下:

@scala.inline
  def identity[A](x : A) : A = { /* compiled code */ }

3 implicitly

當隱式引數列表使用簡寫[T:M] 時,編譯器會新增形式為(implicit arg: M[T]) 的隱式引數列表(實際名稱不是arg,而是編譯器合成的唯一名稱)。呼叫implicitly 可以返回引數arg。原始碼如下:

 @scala.inline
  def implicitly[T](implicit e : T) : T = { /* compiled code */ }

看一個例子:

package cn.com.tengen.test.obj

class Test{

}
case class MyList[A](list: List[A]) {
  def sortBy1[B](f: A => B)(implicit ord: Ordering[B]): List[A] =
    list.sortBy(f)(ord)
  def sortBy2[B : Ordering](f: A => B): List[A] =
    list.sortBy(f)(implicitly[Ordering[B]])
}


object Test {
  def main(args: Array[String]): Unit = {
    val list = MyList(List(1,3,5,2,4))
    val l1 = list sortBy1 (i => -i)
    val l2 = list sortBy2 (i => -i)
    println(l1)
    println(l2)
  }
}
有些集合提供了一些排序方法,List.sortBy 便是其中之一。List.sortBy 方法的第一個引數型別為函式,該輸入函式能夠將函式的輸入引數轉化為另一個滿足math.Ordering 條件的型別。而math.Ordering 是與Java 中的Comparable抽象等同的型別。List.sortBy 方法的另一個引數則為隱式引數,該引數知道如何對型別B 的例項進行排序。

MyList 類提供了兩種方式編寫像sortBy 型別的方法。第一種實現:sortBy1 方法應用了我們已知的語法。該方法接受一個額外的型別為Ordering[B] 的隱式值作為其輸入。呼叫sortBy1 方法時,在當前作用域中一定存在某一Ordering[B] 的物件例項,該例項清楚地知道如何對我們所需要的B 型別物件進行排序。我們認為B 的界限被“上下文”所限定,在這個例子中,上下文限定了B 對例項進行排序的能力。

由於這種Scala 方言應用非常普遍,因此Scala 提供了一個簡化版的語法,這正是第二類實現 sortBy2 所使用的語法。型別引數B : Ordering被稱為 上下文定界( context bound), 它暗指第二個引數列表(也就是那個隱式引數列表)將接受Ordering[B] 例項。

不過,我們仍需要在方法中訪問Ordering 物件例項。由於在原始碼中我們不再明確地宣告Ordering 物件例項,因此這個例項沒有自己的名稱。針對這種現象我們該怎麼辦呢?Predef.implicitly 方法幫我們解決了這個問題。implicitly 方法會對傳給函式的所有標記為隱式引數的例項進行解析。請注意implicitly 方法所需要的型別簽名,在本例中Ordering[B] 是其型別簽名。

4.Pair 與 Triple

Pair是一個二元組,Triple是一個三元組
原始碼:
@scala.deprecated("use built-in tuple syntax or Tuple2 instead", "2.11.0")
  type Pair[+A, +B] = scala.Tuple2[A, B]
  @scala.deprecated("use built-in tuple syntax or Tuple2 instead", "2.11.0")
  object Pair extends scala.AnyRef {
    def apply[A, B](x : A, y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
    def unapply[A, B](x : scala.Tuple2[A, B]) : scala.Option[scala.Tuple2[A, B]] = { /* compiled code */ }
  }
  @scala.deprecated("use built-in tuple syntax or Tuple3 instead", "2.11.0")
  type Triple[+A, +B, +C] = scala.Tuple3[A, B, C]
  @scala.deprecated("use built-in tuple syntax or Tuple3 instead", "2.11.0")
  object Triple extends scala.AnyRef {
    def apply[A, B, C](x : A, y : B, z : C) : scala.Tuple3[A, B, C] = { /* compiled code */ }
    def unapply[A, B, C](x : scala.Tuple3[A, B, C]) : scala.Option[scala.Tuple3[A, B, C]] = { /* compiled code */ }
  }
5. Map與Set

我們先可一個例子:
object Test {
  def main(args: Array[String]): Unit = {
    val map = Map(1->"aaa",2->"BBB")
    val set = Set(1,2,33,44,44,6)
    println(map)
    println(set)
  }
}

這裡我們用的Map和Set都是Predef中的兩個屬性,而並沒有直接匯入scala.collection.immutable.Map和scala.collection.immutable.Set,看原始碼:

 type Map[A, +B] = scala.collection.immutable.Map[A, B]
  type Set[A] = scala.collection.immutable.Set[A]
  val Map : scala.collection.immutable.Map.type = { /* compiled code */ }
  val Set : scala.collection.immutable.Set.type = { /* compiled code */ }