建議語言功能分類
此文件提供 Scala 3 提議建構的概觀,目的是促進討論要包含哪些內容以及何時包含。它將功能分為八組:(1) 基本基礎、(2) 簡化、(3) 限制、(4) 已移除功能、(5) 已變更功能、(6) 新功能、(7) 旨在取代現有巨集的元程式編寫導向功能,以及 (8) 類型檢查和推論的變更。
每個群組都包含分類狀態(即成為 Scala 3 一部分的相對重要性,以及何時決定此問題的相對緊急性)和其中建構的遷移成本的部分。
目前的文檔反映了 2019 年 4 月的現狀。它將更新以反映該狀態的任何未來變更。
基本基礎
這些新建構直接建模 DOT、高階類型和 用於隱式解析的 SI 計算 的核心功能。
狀態:必要
這些是 Scala 3 的必要核心功能。沒有它們,Scala 3 將會是完全不同的語言,具有不同的基礎。
遷移成本:無到低
由於這些是新增功能,因此舊程式碼通常沒有遷移成本。例外情況是交集類型,它以略微清理的語意取代複合類型。但很少程式會受到此變更影響。
簡化
這些建構取代現有建構,目的是使語言更安全、更易於使用,並促進程式碼樣式的統一。
- 特質參數以更通用的建構取代早期初始化程式。
- 給定實例取代隱式物件和 def,專注於意圖而非機制。
- using 子句取代隱式參數,避免其歧義。
- 擴充方法以更清晰、更簡單的機制取代隱式類別。
- 不透明類型別名取代大多數值類別的用法,同時保證沒有裝箱。
- 頂層定義取代套件物件,捨棄語法樣板。
- 匯出子句提供簡單且通用的方式來表達聚合,它可以取代套件物件繼承自類別的先前門面模式。
- 變數參數接合現在使用
*
而不是@ _*
的形式,反映變數參數表達式, - 建立應用程式允許使用簡單的函式呼叫語法,而非
new
表達式。new
表達式仍作為建立應用程式無法使用時的後備方案。
除了早期初始化程式和舊式可變長度引數拼接之外,所有取代的建構在 Scala 3.0 中仍可使用。計畫是將其標示為不建議使用,並在稍後逐步淘汰。
值類別(被不透明類型別名取代)是一個特例。目前沒有針對值類別的淘汰計畫,因為如果專案 Valhalla 如計畫般由 JVM 原生支援,我們可能會以更通用的形式將其帶回。
狀態:雙模:現在或永遠 / 可延後
這些是必要的簡化。如果我們決定採用它們,我們應該在 3.0 中執行。否則我們將面臨一個尷尬的狀況,即 Scala 3 文件必須描述一個舊功能,而該功能將來會被更簡單的功能取代或取代。
另一方面,我們現在只需要決定此清單中的新功能。放棄取代功能的決定可以延後。當然,採用新功能而不決定放棄取代功能會使語言變大。
遷移成本:中等
在接下來的幾個版本中,舊功能仍將可用,並且淘汰和重寫技術可以使任何遷移工作變得低且漸進。
限制
這些建構受到限制,以使語言更安全。
- 隱式轉換:只有一種方法可以定義隱式轉換,而不是許多,而且可能令人驚訝的隱式轉換需要語言匯入。
- 已給予匯入:隱式現在需要特殊形式的匯入,以使匯入清楚可見。
- 類型投影:只有類別可用作類型投影
C#A
的前綴C
。不再支援抽象類型的類型投影,因為它不健全。 - 多重宇宙等價實作「選擇加入」的方案,以排除使用
==
和!=
進行無意義的比較。 - 中綴運算子讓方法應用語法在所有程式碼庫中統一。
Scala 3.0 仍提供不受限制的隱式轉換,但稍後會標示為過時並移除。上述清單中其他建構的不受限制版本僅在 -source 3.0-migration
下可用。
狀態:現在或永遠
這些是必要的限制。如果我們決定採用這些限制,我們應該在 3.0 中執行。否則,我們將面臨一個尷尬的情況,即 Scala 3 文件必須描述未來將受到限制的功能。
遷移成本:低到高
- 低:多重宇宙等價排除了無意義的程式碼,因此採用它所需的任何重寫都應歸類為錯誤修正。
- 中等:透過直接重寫,可以解決隱式的限制。
- 高:不受限制的類型投影無法總是直接重寫,因為它通常是不健全的。
已移除的建構
建議移除這些建構,而不會有新的建構取代它們。移除這些建構的動機是簡化語言及其實作。
移除這些建構的日期有所不同。目前的狀態為
- 尚未實作
- DelayedInit、存在類型、弱一致性。
- 在
-source 3.0-migration
中受到支援- 程序語法、類別遮蔽、符號文字、自動應用、自動組元(受限形式)。
- 在 3.0 中受到支援,將在稍後棄用並逐步淘汰
- XML 文字、複合類型。
狀態:混合
目前未實作的功能需要大量的實作工作,在多數情況下會讓編譯器變得更多錯誤、脆弱,且更難理解。如果我們不決定放棄這些功能,它們可能會在 Scala 3.0 版本中顯示為「尚未實作」。
目前已實作的功能可能會無限期地保留。更新的文件可能會忽略它們,並預期它們最終會消失。因此,關於移除它們的決定可以延後。
遷移成本:中度至高
已放棄的功能需要重寫,以避免在程式中使用它們。這些重寫有時可以自動進行(例如,對於程序語法、符號文字、自動應用),有時需要手動進行(例如,類別遮蔽、自動組元)。有時,重寫必須是非本地的,影響使用位置和定義位置(例如,在 DelayedInit
的情況下,除非我們找到解決方案)。
變更
這些建構已進行變更,使其更規律且有用。
- 結構化類型:它們現在允許插入式實作,這大大增加了它們的實用性。與現狀相比,某些使用模式受到限制。
- 基於名稱的模式比對:現有的未記錄 Scala 2 實作已以略微簡化的形式編纂。
- Eta 展開 現在在沒有預期類型的情況下也普遍執行。因此,後綴
_
算子變得多餘。它將在 Scala 3.0 之後棄用並刪除。 - 隱式解析度:隱式解析度規則已清理,使其更實用且不那麼令人驚訝。隱式範圍已限制為不再包含封裝前綴。
舊式隱式解析度的大部分面向仍可在 -source 3.0-migration
下使用。此清單中的其他變更會無條件套用。
狀態:強烈建議
這些功能已在 Scala 3.0 的編譯器中以其新形式實作。與現狀相比,它們在簡潔性和功能性方面提供了明確的改進。要回溯需要大量的實作工作,但功能性卻會淨損失。
遷移成本:低到高
只有少數程式需要變更,但一些必要的變更可能是非本地的(例如隱式範圍的限制)。
新結構
這些是語言的附加功能,使它更強大或更易於使用。
- 列舉提供簡潔的語法,用於列舉和代數資料類型。
- 參數取消封裝避免必須使用
case
進行封裝參數解構。 - 相依函數類型將相依方法概括為相依函數值和類型。
- 多型函數類型將多型方法概括為相依函數值和類型。目前狀態:有一個提案和一個原型實作,但實作尚未定稿或合併。
- 類型多型允許定義同時作用於類型和類型建構函式的運算子。
狀態:混合
列舉提供了基本使用模式的必要簡化,因此應採用於 Scala 3.0。自動參數封裝是一個很小的變更,消除了某些尷尬,因此現在就可以採用。其他功能構成更專業化的功能,可以在後續版本中引入。另一方面,除了多型函數類型之外,它們都已完全實作,因此,如果 Scala 3.0 規格不包含它們,它們仍可能在語言標記下提供。
遷移成本:無
由於是新功能,現有程式碼在遷移時不需要變更。當然,有時為了增加清晰度和簡潔度,改寫程式碼以使用新功能會很有吸引力。
元程式設計
以下建構共同旨在為 Scala 中的元程式設計奠定新的基礎。到目前為止,元程式設計是透過巨集和函式庫(例如 Shapeless)的組合來達成,而這些函式庫又是建立在一些關鍵巨集之上。目前的 Scala 2 巨集機制是建立在目前的 Scala 2 編譯器之上的一層薄薄的飾面,這使得它們很脆弱,而且在許多情況下無法移植到 Scala 3。
值得注意的是,巨集從未包含在 Scala 2 語言規範 中,而且到目前為止僅在 -experimental
旗標下提供。這並未阻止它們被廣泛使用。
為了讓大多數巨集用法都能移植,我們正在嘗試使用下面列出的進階語言建構。這些設計比 Scala 3.0 提出的其他語言建構更具暫時性。在最終版本之前,可能仍會有一些變更。穩定元程式設計所需的特性集是我們的首要任務。
- 比對類型允許對類型進行運算。
- 內嵌本身提供了一些簡單巨集的直接實作,同時也是實作複雜巨集的基本建構模組。
- 引號和拼接提供了一種原則性的方式來表達巨集和分段,並使用一組統一的抽象。
- 型別類別推導在語言內提供 Shapeless 和其他基礎函式庫中
Gen
巨集的實作。新的實作比巨集更強大、更有效率且更容易使用。 - <隱含依名稱參數在語言內提供 Shapeless 中
Lazy
巨集更強大的實作。
狀態:尚未確定
我們知道我們需要一個實用的方法來取代目前的巨集。上述列出的功能在這方面非常有希望,但我們需要更完整的實作和更多使用案例才能做出最終的決定。
遷移成本:非常高
現有的巨集函式庫必須從頭開始重寫。在許多情況下,重寫的函式庫將會比舊的函式庫更簡單、更強大,但這並不能減輕重寫的成本。目前尚不清楚巨集函式庫使用者將受到何種程度的影響。我們的目標是提供足夠的功能,以便核心巨集可以完全重新實作,但由於 Scala 2 的各種巨集擴充功能的龐大功能集,很難達到可行的範圍限制。
變更型別檢查和推論
Scala 3 編譯器使用新的演算法進行型別推論,這依賴於一般的子型別約束求解器。新的演算法通常比舊的演算法更好,但不可避免地會出現兩種演算法的結果不同的情況,導致 Scala 3 診斷出 Scala 2 編譯器接受的程式錯誤。
狀態:必要
新的型別檢查和推論演算法是新編譯器的基本核心。它們無法在不放棄 Scala 3 的整個實作的情況下復原。
遷移成本:高
某些現有程式會中斷,且考量到類型推論的複雜性,並非總是清楚是什麼變更造成中斷以及如何修復。
根據我們的經驗,巨集和類型與隱式參數推論的變更共同造成將現有程式移植到 Scala 3 時遇到的絕大多數問題。後者問題的來源可以透過工具系統性地解決,該工具會將所有推論的類型和隱式參數新增到 Scala 2 原始程式碼檔案。這種工具最有可能會實作為 Scala 2 編譯器外掛程式。產生的程式在 Scala 3 下編譯的可能性會大幅提高,但通常會龐大到無法讀取。重寫工具的第二部分應該有選擇性且反覆移除第一部分合成,且在 Scala 3 下編譯的類型和隱式註解。第二部分可以實作為呼叫 Scala 3 編譯器 scalac
程式的程式。
幾個人已經提出這種工具一段時間了。我相信是時候找到意願和資源來實際實作它了。