Scala 速查表

Scala 速查表

語言

感謝 Brendan O’Connor,此速查表旨在作為 Scala 語法結構的快速參考。由 Brendan O’Connor 根據 CC-BY-SA 3.0 授權。

變數
var x = 5

良好
x = 6
變數。
val x = 5

不佳
x = 6
常數。
var x: Double = 5
明確類型。
函式
良好
def f(x: Int) = { x * x }

不佳
def f(x: Int)   { x * x }
定義函式。
隱藏錯誤:如果沒有 =,它是一個傳回 Unit 的程序;會造成混亂。 已棄用 Scala 2.13。
良好
def f(x: Any) = println(x)

不佳
def f(x) = println(x)
定義函式。
語法錯誤:每個參數都需要類型。
type R = Double
類型別名。
def f(x: R)
相較於
def f(x: => R)
依值呼叫。

依名稱呼叫(延遲參數)。
(x: R) => x * x
匿名函式。
(1 to 5).map(_ * 2)
相較於
(1 to 5).reduceLeft(_ + _)
匿名函式:底線是位置匹配參數。
(1 to 5).map(x => x * x)
匿名函式:要使用參數兩次,必須命名它。
(1 to 5).map { x =>
  val y = x * 2
  println(y)
  y
}
匿名函式:區塊樣式傳回最後一個表達式。
(1 to 5) filter {
  _ % 2 == 0
} map {
  _ * 2
}
匿名函式:管線樣式(或括號)。
def compose(g: R => R, h: R => R) =
  (x: R) => g(h(x))

val f = compose(_ * 2, _ - 1)
匿名函式:要傳入多個區塊,需要外層括號。
val zscore =
  (mean: R, sd: R) =>
    (x: R) =>
      (x - mean) / sd
柯里化,明顯的語法。
def zscore(mean: R, sd: R) =
  (x: R) =>
    (x - mean) / sd
柯里化,明顯的語法。
def zscore(mean: R, sd: R)(x: R) =
  (x - mean) / sd
柯里化,糖衣語法。但接著
val normer =
  zscore(7, 0.4) _
需要尾隨底線才能取得部分,僅適用於糖衣版本。
def mapmake[T](g: T => T)(seq: List[T]) =
  seq.map(g)
泛型類型。
5.+(3); 5 + 3

(1 to 5) map (_ * 2)
中綴糖衣語法。
def sum(args: Int*) =
  args.reduceLeft(_+_)
可變參數。
封包
import scala.collection._
萬用字元匯入。
import scala.collection.Vector

import scala.collection.{Vector, Sequence}
選擇性匯入。
import scala.collection.{Vector => Vec28}
重新命名匯入。
import java.util.{Date => _, _}
匯入 java.util 中的所有內容,但 Date 除外。
在檔案開頭
package pkg

依範圍封裝
package pkg {
  ...
}

封裝單例
package object pkg {
  ...
}
宣告一個封裝。
資料結構
(1, 2, 3)
元組文字 (Tuple3)。
var (x, y, z) = (1, 2, 3)
解構繫結:透過模式比對解開元組。
不佳
var x, y, z = (1, 2, 3)
隱藏錯誤:每個都指定給整個元組。
var xs = List(1, 2, 3)
清單(不可變)。
xs(2)
括號索引 (投影片)。
1 :: List(2, 3)
Cons。
1 to 5
1 until 6

1 to 10 by 2
範圍糖衣。
()
空的括號是單元類型中的單例值。
等同於 C 和 Java 中的 void
控制建構
if (check) happy else sad
條件式。
if (check) happy


if (check) happy else ()
條件式糖衣。
while (x < 5) {
  println(x)
  x += 1
}
While 迴圈。
do {
  println(x)
  x += 1
} while (x < 5)
Do-while 迴圈。
import scala.util.control.Breaks._
breakable {
  for (x <- xs) {
    if (Math.random < 0.1)
      break
  }
}
中斷 (投影片)。
for (x <- xs if x % 2 == 0)
  yield x * 10


xs.filter(_ % 2 == 0).map(_ * 10)
For-comprehension:篩選/映射。
for ((x, y) <- xs zip ys)
  yield x * y


(xs zip ys) map {
  case (x, y) => x * y
}
For-comprehension:解構繫結。
for (x <- xs; y <- ys)
  yield x * y


xs flatMap { x =>
  ys map { y =>
    x * y
  }
}
For-comprehension:笛卡兒積。
for (x <- xs; y <- ys) {
  val div = x / y.toFloat
  println("%d/%d = %.1f".format(x, y, div))
}
For-comprehension:命令式。
sprintf 樣式.
for (i <- 1 to 5) {
  println(i)
}
For-comprehension:包含上界進行反覆。
for (i <- 1 until 5) {
  println(i)
}
For-comprehension:省略上界進行反覆。
模式比對
良好
(xs zip ys) map {
  case (x, y) => x * y
}

不佳
(xs zip ys) map {
  (x, y) => x * y
}
函式引數中的使用案例,用於模式比對。
不佳
val v42 = 42
3 match {
  case v42 => println("42")
  case _   => println("Not 42")
}
v42 被解釋為與任何 Int 值比對的名稱,並印出「42」。
良好
val v42 = 42
3 match {
  case `v42` => println("42")
  case _     => println("Not 42")
}
帶有反引號的 `v42` 被解釋為現有的 val v42,並印出「Not 42」。
良好
val UppercaseVal = 42
3 match {
  case UppercaseVal => println("42")
  case _            => println("Not 42")
}
UppercaseVal 被視為現有的 val,而不是新的模式變數,因為它以大寫字母開頭。因此,會檢查 UppercaseVal 中包含的值與 3,並印出「Not 42」。
物件導向
class C(x: R)
建構函式參數 - x 僅在類別本體中可用。
class C(val x: R)

var c = new C(4)

c.x
建構函式參數 - 自動定義公開成員。
class C(var x: R) {
  assert(x > 0, "positive please")
  var y = x
  val readonly = 5
  private var secret = 1
  def this() = this(42)
}
建構函式是類別本體。
宣告一個公開成員。
宣告一個可取得但不可設定的成員。
宣告一個私有成員。
替代建構函式。
new {
  ...
}
匿名類別。
abstract class D { ... }
定義一個抽象類別(不可建立)。
class C extends D { ... }
定義一個繼承類別。
class D(var x: R)

class C(x: R) extends D(x)
繼承和建構函式參數(願望清單:預設自動傳遞參數)。
object O extends D { ... }
定義一個單例(類似模組)。
trait T { ... }

class C extends T { ... }

class C extends D with T { ... }
特質。
帶有實作的介面。沒有建構函式參數。 可混入
trait T1; trait T2

class C extends T1 with T2

class C extends D with T1 with T2
多個特質。
class C extends D { override def f = ...}
必須宣告方法覆寫。
new java.io.File("f")
建立物件。
不佳
new List[Int]

良好
List(1, 2, 3)
類型錯誤:抽象類型。
相反地,慣例:可呼叫的工廠取代類型。
classOf[String]
類別文字。
x.isInstanceOf[String]
類型檢查(執行時期)。
x.asInstanceOf[String]
類型轉換(執行時期)。
x: String
歸屬(編譯時期)。
選項
Some(42)
建構一個非空選用值。
None
單例空選用值。
Option(null) == None
Option(obj.unsafeMethod)
但是
Some(null) != None
空安全選用值工廠。
val optStr: Option[String] = None
val optStr = Option.empty[String]
空選用值的明確類型。
空選用值工廠。
val name: Option[String] =
  request.getParameter("name")
val upper = name.map {
  _.trim
} filter {
  _.length != 0
} map {
  _.toUpperCase
}
println(upper.getOrElse(""))
管線樣式。
val upper = for {
  name <- request.getParameter("name")
  trimmed <- Some(name.trim)
    if trimmed.length != 0
  upper <- Some(trimmed.toUpperCase)
} yield upper
println(upper.getOrElse(""))
For-comprehension 語法。
option.map(f(_))
option match {
  case Some(x) => Some(f(x))
  case None    => None
}
在選用值上套用函數。
option.flatMap(f(_))
option match {
  case Some(x) => f(x)
  case None    => None
}
與 map 相同,但函數必須傳回選用值。
optionOfOption.flatten
optionOfOption match {
  case Some(Some(x)) => Some(x)
  case _             => None
}
萃取巢狀選項。
option.foreach(f(_))
option match {
  case Some(x) => f(x)
  case None    => ()
}
在選用值上套用程序。
option.fold(y)(f(_))
option match {
  case Some(x) => f(x)
  case None    => y
}
在選用值上套用函數,若為空則傳回預設值。
option.collect {
  case x => ...
}
option match {
  case Some(x) if f.isDefinedAt(x) => ...
  case Some(_)                     => None
  case None                        => None
}
在選用值上套用部分模式比對。
option.isDefined
option match {
  case Some(_) => true
  case None    => false
}
若不為空則為 true
option.isEmpty
option match {
  case Some(_) => false
  case None    => true
}
若為空則為 true
option.nonEmpty
option match {
  case Some(_) => true
  case None    => false
}
若不為空則為 true
option.size
option match {
  case Some(_) => 1
  case None    => 0
}
若為空則為 0,否則為 1
option.orElse(Some(y))
option match {
  case Some(x) => Some(x)
  case None    => Some(y)
}
若為空則評估並傳回備用選用值。
option.getOrElse(y)
option match {
  case Some(x) => x
  case None    => y
}
若為空則評估並傳回預設值。
option.get
option match {
  case Some(x) => x
  case None    => throw new Exception
}
傳回值,若為空則擲回例外。
option.orNull
option match {
  case Some(x) => x
  case None    => null
}
傳回值,若為空則為 null
option.filter(f)
option match {
  case Some(x) if f(x) => Some(x)
  case _               => None
}
選用值符合謂詞。
option.filterNot(f(_))
option match {
  case Some(x) if !f(x) => Some(x)
  case _                => None
}
選用值不符合謂詞。
option.exists(f(_))
option match {
  case Some(x) if f(x) => true
  case Some(_)         => false
  case None            => false
}
在選用值上套用謂詞,或在為空時套用 false
option.forall(f(_))
option match {
  case Some(x) if f(x) => true
  case Some(_)         => false
  case None            => true
}
在選用值上套用謂詞,或在為空時套用 true
option.contains(y)
option match {
  case Some(x) => x == y
  case None    => false
}
檢查值是否等於選用值,或在為空時檢查是否等於 false

此頁面的貢獻者