使用 Scala 有許多好處,尤其是 Scala 3。很難列出 Scala 的所有好處,但「十大」清單可能如下所示
- Scala 融合了函式程式設計 (FP) 和物件導向程式設計 (OOP)
- Scala 是靜態型別,但通常感覺像動態型別語言
- Scala 的語法簡潔,但仍然可讀;它通常被稱為表達性
- Scala 2 中的隱含是一個定義特徵,它們在 Scala 3 中已得到改進和簡化
- Scala 與 Java 無縫整合,因此您可以建立包含 Scala 和 Java 混合程式碼的專案,且 Scala 程式碼可以輕鬆使用數千個現有的 Java 函式庫
- Scala 可用於伺服器,也可透過 Scala.js 用於瀏覽器
- Scala 標準函式庫有數十種預建的函式方法,可節省您的時間,並大幅減少撰寫自訂
for
迴圈和演算法的需求 - 「最佳實務」已內建到 Scala 中,它支持不可變性、匿名函式、高階函式、模式比對、預設無法延伸的類別,以及更多
- Scala 生態系統提供世界上最現代化的 FP 函式庫
- 強大的型別系統
1) FP/OOP 融合
Scala 比任何其他語言更支援 FP 和 OOP 範例的融合。正如 Martin Odersky 所述,Scala 的精髓在於在類型化設定中融合函式式和物件導向程式設計,其中
- 函式用於邏輯,而
- 物件用於模組化
模組化的最佳範例之一可能是標準函式庫中的類別。例如,List
被定義為一個類別,技術上來說,它是一個抽象類別,而新的實例會像這樣建立
val x = List(1, 2, 3)
然而,程式設計師眼中看似簡單的 List
實際上是由多個專門類型組合而成,其中包括名為 Iterable
、Seq
和 LinearSeq
的特質。這些類型也由其他小型模組化程式碼單元組成。
除了從一系列模組化特質建立 List
等類型之外,List
API 還包含數十個其他方法,其中許多是高階函式
val xs = List(1, 2, 3, 4, 5)
xs.map(_ + 1) // List(2, 3, 4, 5, 6)
xs.filter(_ < 3) // List(1, 2)
xs.find(_ > 3) // Some(4)
xs.takeWhile(_ < 3) // List(1, 2)
在這些範例中,清單中的值無法修改。List
類別是不可變的,因此所有這些方法都會傳回新值,如每個註解中的資料所示。
2) 動態感
Scala 的類型推論通常讓語言感覺是動態類型的,即使它是靜態類型的。這在變數宣告中是正確的
val a = 1
val b = "Hello, world"
val c = List(1,2,3,4,5)
val stuff = ("fish", 42, 1_234.5)
在將匿名函式傳遞給高階函式時也是如此
list.filter(_ < 4)
list.map(_ * 2)
list.filter(_ < 4)
.map(_ * 2)
以及在定義方法時
def add(a: Int, b: Int) = a + b
在 Scala 3 中,這比以往任何時候都更為真實,例如在使用聯合類型時
// union type parameter
def help(id: Username | Password) =
val user = id match
case Username(name) => lookupName(name)
case Password(hash) => lookupPassword(hash)
// more code here ...
// union type value
val b: Password | Username = if (true) name else password
3) 簡潔的語法
Scala 是一種低儀式感、「簡潔但仍可讀」的語言。例如,變數宣告很簡潔
val a = 1
val b = "Hello, world"
val c = List(1,2,3)
建立特質、類別和列舉等類型很簡潔
trait Tail:
def wagTail(): Unit
def stopTail(): Unit
enum Topping:
case Cheese, Pepperoni, Sausage, Mushrooms, Onions
class Dog extends Animal, Tail, Legs, RubberyNose
case class Person(
firstName: String,
lastName: String,
age: Int
)
高階函式很簡潔
list.filter(_ < 4)
list.map(_ * 2)
所有這些表達式以及更多表達式都很簡潔,而且仍然非常容易閱讀:我們稱之為表達。
4) 簡化的隱含式
Scala 2 中的隱含式是一個主要的區別設計功能。它們代表了抽象化 over context 的基本方式,並採用統一的範例,服務於各種使用案例,其中包括
- 實作 類型類別
- 建立內容
- 相依性注入
- 表達功能
從那時起,其他語言採用了類似的概念,這些概念都是核心概念 術語推論 的變體:給定一個類型,編譯器會綜合一個具有該類型的「正規」術語。
雖然隱含式是 Scala 2 中的定義功能,但它們的設計在 Scala 3 中已獲得極大的改善
- 定義「給定」值的方法只有一個
- 引入隱含式參數和引數的方法只有一個
- 有一種單獨的方法來匯入給定值,而不會讓它們隱藏在大量的正常匯入中
- 定義隱含式轉換的方法只有一個,會清楚標示為隱含式轉換,而且不需要特殊語法
這些變更的優點包括
- 新的設計避免功能互動,讓語言更一致
- 它讓隱含式更容易學習,更難濫用
- 它大幅提升使用隱含式的 95% Scala 程式碼的清晰度
- 它有潛力以有原則的方式啟用術語推論,而且這種方式也能被存取且友善
這些功能在其他章節中有詳細說明,因此請參閱 內容抽象簡介,以及 given
和 using
子句 章節,以取得更多詳細資訊。
5) 無縫 Java 整合
Scala/Java 互動在許多方面都是無縫的。例如
- 您可以在 Scala 專案中使用數以千計的 Java 函式庫
- Scala
String
本質上是 JavaString
,並新增額外的功能 - Scala 會無縫使用 Java java.time._ 套件中的日期/時間類別
您也可以在 Scala 中使用 Java 集合類別,而為了提供更多功能,Scala 包含方法,讓您可以將它們轉換為 Scala 集合。
雖然幾乎每個互動都是無縫的,但 「與 Java 互動」章節 示範如何更好地一起使用一些功能,包括如何使用
- Scala 中的 Java 集合
- Scala 中的 Java
Optional
- Scala 中的 Java 介面
- Java 中的 Scala 集合
- Java 中的 Scala
Option
- Java 中的 Scala 特質
- Java 程式碼中會擲回例外狀況的 Scala 方法
- Java 中的 Scala 變數參數
請參閱該章節以取得這些功能的更多詳細資訊。
6) 伺服器端與用戶端
Scala 可以搭配強大的架構在伺服器端使用
- Play Framework 讓您可以建置高度可擴充的伺服器端應用程式和微服務
- Akka Actors 讓您可以使用 Actor 模型大幅簡化分散式和並行軟體應用程式
Scala 也能搭配 Scala.js 專案 在瀏覽器中使用,這是一個 JavaScript 的類型安全替代方案。Scala.js 生態系 有數十個函式庫 讓您可以在瀏覽器中使用 React、Angular、jQuery 和許多其他 JavaScript 和 Scala 函式庫。
除了這些工具之外,Scala Native 專案「是一個特別為 Scala 設計的最佳化即時編譯器和輕量級受控執行時期」。它讓您可以使用純粹的 Scala 程式碼建置「系統」樣式的二進位可執行應用程式,而且還能讓您使用較低層級的原語。
7) 標準函式庫方法
您幾乎不需要再撰寫自訂 for
迴圈,因為 Scala 標準函式庫中的數十個預先建置函數方法將會為您節省時間,並協助讓程式碼在不同的應用程式中更一致。
以下範例顯示一些內建集合方法,還有許多方法未在此列出。雖然這些範例都使用 List
類別,但相同的這些方法也可以搭配其他集合類別使用,例如 Seq
、Vector
、LazyList
、Set
、Map
、Array
和 ArrayBuffer
。
以下是一些範例
List.range(1, 3) // List(1, 2)
List.range(start = 1, end = 6, step = 2) // List(1, 3, 5)
List.fill(3)("foo") // List(foo, foo, foo)
List.tabulate(3)(n => n * n) // List(0, 1, 4)
List.tabulate(4)(n => n * n) // List(0, 1, 4, 9)
val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10)
a.distinct // List(10, 20, 30, 40)
a.drop(2) // List(30, 40, 10)
a.dropRight(2) // List(10, 20, 30)
a.dropWhile(_ < 25) // List(30, 40, 10)
a.filter(_ < 25) // List(10, 20, 10)
a.filter(_ > 100) // List()
a.find(_ > 20) // Some(30)
a.head // 10
a.headOption // Some(10)
a.init // List(10, 20, 30, 40)
a.intersect(List(19,20,21)) // List(20)
a.last // 10
a.lastOption // Some(10)
a.map(_ * 2) // List(20, 40, 60, 80, 20)
a.slice(2, 4) // List(30, 40)
a.tail // List(20, 30, 40, 10)
a.take(3) // List(10, 20, 30)
a.takeRight(2) // List(40, 10)
a.takeWhile(_ < 30) // List(10, 20)
a.filter(_ < 30).map(_ * 10) // List(100, 200, 100)
val fruits = List("apple", "pear")
fruits.map(_.toUpperCase) // List(APPLE, PEAR)
fruits.flatMap(_.toUpperCase) // List(A, P, P, L, E, P, E, A, R)
val nums = List(10, 5, 8, 1, 7)
nums.sorted // List(1, 5, 7, 8, 10)
nums.sortWith(_ < _) // List(1, 5, 7, 8, 10)
nums.sortWith(_ > _) // List(10, 8, 7, 5, 1)
8) 內建最佳實務
Scala 慣用語法在許多方面鼓勵最佳實務。對於不變性,我們鼓勵您建立不變的 val
宣告
val a = 1 // immutable variable
我們也鼓勵您使用不變集合類別,例如 List
和 Map
val b = List(1,2,3) // List is immutable
val c = Map(1 -> "one") // Map is immutable
案例類別主要用於 網域建模,其參數是不變的
case class Person(name: String)
val p = Person("Michael Scott")
p.name // Michael Scott
p.name = "Joe" // compiler error (reassignment to val name)
如前一節所示,Scala 集合類別支援高階函數,您可以將方法(未顯示)和匿名函數傳遞給它們
a.dropWhile(_ < 25)
a.filter(_ < 25)
a.takeWhile(_ < 30)
a.filter(_ < 30).map(_ * 10)
nums.sortWith(_ < _)
nums.sortWith(_ > _)
match
表達式讓你可以使用樣式比對,而且它們真的是會傳回值的表達式
val numAsString = i match {
case 1 | 3 | 5 | 7 | 9 => "odd"
case 2 | 4 | 6 | 8 | 10 => "even"
case _ => "too big"
}
val numAsString = i match
case 1 | 3 | 5 | 7 | 9 => "odd"
case 2 | 4 | 6 | 8 | 10 => "even"
case _ => "too big"
因為它們可以傳回值,所以通常會用作方法的主體
def isTruthy(a: Matchable) = a match {
case 0 | "" => false
case _ => true
}
def isTruthy(a: Matchable) = a match
case 0 | "" => false
case _ => true
9) 生態系統函式庫
像 Cats 和 Zio 這樣的 Scala 函式庫是 FP 社群中的領先函式庫。所有像高性能、類型安全、並行、非同步、資源安全、可測試、函式式、模組化、二進位相容、高效、效應/有效果等時髦用語都可以用在這些函式庫上。
我們可以列出數百個函式庫,但幸運的是它們都列在另一個位置:有關這些詳細資訊,請參閱 “Awesome Scala” 清單。
10) 強類型系統
Scala 有強類型系統,而且在 Scala 3 中進一步改進。Scala 3 的目標很早就定義,與類型系統相關的目標包括
- 簡化
- 消除不一致
- 安全性
- 人體工學
- 效能
簡化是透過數十項變更和取消的功能而來。例如,從 Scala 2 中的過載 implicit
關鍵字變更為 Scala 3 中的 given
和 using
這些術語,讓語言更清楚,特別是對於初學開發人員來說。
消除不一致與 Scala 3 中數十項 取消的功能、變更的功能 和 新增的功能 有關。此類別中一些最重要的功能是
- 交集類型
- 聯集類型
- 隱式函式類型
- 相依函式類型
- 特質參數
- 泛型元組
安全性與多項新增和變更的功能有關
- 多重相等
- 限制隱式轉換
- 空值安全性
- 安全初始化
人體工學的良好範例是列舉和擴充方法,它們已以非常易讀的方式新增到 Scala 3
// enumeration
enum Color:
case Red, Green, Blue
// extension methods
extension (c: Circle)
def circumference: Double = c.radius * math.Pi * 2
def diameter: Double = c.radius * 2
def area: Double = math.Pi * c.radius * c.radius
效能與多個領域有關。其中之一是 不透明類型。在 Scala 2 中,曾嘗試建立解決方案來遵循領域驅動設計 (DDD) 的做法,為值提供更有意義的類型。這些嘗試包括
- 類型別名
- 值類別
- 案例類別
不幸的是,所有這些方法都有弱點,如 不透明類型 SIP 中所述。相反,如該 SIP 中所述,不透明類型的目標是「這些包裝器類型的運算不應在執行階段產生任何額外開銷,同時仍提供編譯階段的類型安全使用。」
有關更多類型系統詳細資訊,請參閱 參考文件。
其他優異功能
Scala 有許多優異功能,而選擇前 10 名清單可能會很主觀。多項調查顯示,不同群組的開發人員喜愛不同的功能。希望您在使用此語言時,能發現更多優異的 Scala 功能。