5.9 KiB
Erg design's "Why" and Answers
當我們有所有權系統時,為什么要與 GC 共存?
因為 Erg 推出所有權系統的動機并不是為了 Rust 那樣的“不依賴 GC 的內存管理”。最初,由于 Erg 是一種語言,目前使用 Python VM,因此最終仍使用 GC。Erg 引入產權系統的目標是“可變狀態的局部化”。在 Erg 中,可變對象具有所有權概念。這是根據共享可變狀態容易成為 bug 的溫床,甚至是類型安全性的侵犯(詳見)來判斷的。
為什么類型參數周圍的括號不是 <> 或 []?
因為在和中會發生語法沖突。
# []版
id[T: Type] [t]: [T] = t
y = id[Int] # 這是一個功能嗎?
# <>版
id<T: Type> {t: T} = t
y = (id<Int, 1> 1) # 這是一個元組嗎?
# {}版
id{T: Type} {t: T} = t
y = id{Int} # 這是一個功能嗎?
# ||版
id|T: Type| t: T = t
y = id|Int| # OK
{i=1} 的類型為 {i=Int},但在 OCaml 等環境中為 {i:Int}。為什么 Erg 采用前者的語法?
Erg 設計為將類型本身也視為值。
A = [Int; 3]
assert A[2] == Int
T = (Int, Str)
assert T.1 == Str
D = {Int: Str}
assert D[Int] == Str
S = {.i = Int}
assert S.i == Int
你打算在 Erg 中實現宏嗎?
目前沒有。宏觀大致分為四個目的。第一個是編譯時計算。這在 Erg 中由編譯時函數負責。第二,代碼執行的延遲。這可以用 do 塊來代替。第三個是處理通用化,對此多相關數和全稱類型是比宏觀更好的解決方案。第四個是自動生成代碼,但這會造成可讀性的下降,所以我們不敢在 Erg 中實現。因此,宏的大部分功能都由 Erg 型系統承擔,因此沒有動力進行部署。
為什么 Erg 沒有例外機制?
在許多情況下,錯誤處理類型是更好的解決方案。類型<gtr=“9”/>是一種錯誤處理方法,通常在較新的編程語言中使用。
在 Erg 中,運算符使你可以在不太注意錯誤的情況下編寫。
read_file!() =
f = open!("foo.txt")? # 如果失敗則立即返回錯誤,所以 f 是文件類型
f.read_all!()
# 也可以使用 try 過程捕獲類似的異常
try!:
do!
s = read_file!()?
print! s
e =>
# 發生錯誤時執行的塊
print! e
exit 1
在引入 Python 函數時,缺省情況下,所有函數都被視為包含異常,返回類型為。如果你知道不調度異常,請在<gtr=“12”/>中指明。
此外,Erg 沒有引入異常機制的另一個原因是它計劃引入并行編程的功能。這是因為異常機制與并行執行不兼容(例如,如果并行執行導致多個異常,則很難處理)。
Erg 似乎消除了 Python 被認為是壞做法的功能,但為什么沒有取消繼承?
Python 的庫中有一些類設計為繼承,如果完全取消繼承,這些操作就會出現問題。然而,由于 Erg 的類默認為 final,并且原則上禁止多重和多層繼承,因此繼承的使用相對安全。
為什么多相關數的子類型推理默認指向記名trait?
默認情況下,指向結構托盤會使類型指定變得復雜,并且可能會混合程序員的非預期行為。
# 如果 T 是結構特征的子類型...
# f: |T <: Structural Trait {.`_+_` = Self.(Self) -> Self; .`_-_` = Self.(Self) -> Self}| (T, T) -> T
f|T| x, y: T = x + y - x
# T 是名義特征的子類型
# g: |T <: Add() and Sub()| (T, T) -> T
g|T| x, y: T = x + y - x
Erg 是否實現了定義自己的運算符的功能?
A:沒有那個計劃。最重要的原因是,如果允許定義自己的運算符,就會出現如何處理組合順序的問題。可以定義自己的運算符的 Scala 和 Haskell 等都有不同的對應,但這可以看作是可能產生解釋差異的語法的證據。此外,獨立運算符還有一個缺點,那就是可能產生可讀性較低的代碼。
為什么 Erg 取消了 += 這樣的擴展賦值運算符?
首先,Erg 中沒有變量的可變性。也就是不能重新賦值。一旦對象與一個變量關聯,它將一直綁定到該變量,直到它脫離作用域并被釋放。在 Erg 中,可變性是指對象的可變性。明白了這個,故事就簡單了。例如,表示<gtr=“14”/>,但由于變量是不可重新賦值的,因此這種語法是非法的。還有一個 Erg 的設計原則是運算符沒有副作用。Python 通常也是如此,但對于某些對象(如 Dict),擴展賦值運算符會更改對象的內部狀態。這算不上是一個很漂亮的設計。因此,擴展賦值運算符被完全廢棄。
為什么 Erg 在語法上特別對待有副作用的過程?
副作用的局部化是代碼維護的一個關鍵因素。
但是,確實也不是沒有方法可以不在語言上特殊對待副作用。例如,可以用代數效果(類型系統上的功能)替代過程。但這樣的合一并不總是正確的。例如,Haskell 沒有對字符串進行特殊處理,只是一個字符數組,但這種抽象是錯誤的。
什么情況下,可以說合一化是錯的?一個指標是“是否會因其合一而難以看到錯誤信息”。Erg 設計師發現,將副作用特殊處理會使錯誤消息更容易閱讀。
Erg 有一個強大的類型系統,但并不是所有的類型都決定了它。如果這樣做了,你的下場就跟 Java 試圖用類來控制一切一樣。