變數 |
|
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 。 |