erg/doc/zh_CN/dev_guide/faq_syntax.md

108 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Erg design's "Why" and Answers
## 为什么有产权体系GC 也让它共存?
因为 Erg 推出所有权系统的动机并不是为了 Rust 那样的“不依赖 GC 的内存管理”。最初,由于 Erg 是一种语言,目前已被 Python 字节码删除,因此最终仍使用 GC。Erg 引入产权系统的目标是“可变状态的局部化”。在 Erg 中,可变对象具有所有权概念。这是根据共享可变状态容易成为 bug 的温床,甚至是类型安全性的侵犯(详见)来判断的。
## 为什么类型参数周围的括号不是 <> 或 []
因为在和<gtr=“7/>中会发生语法冲突。
```erg
# []版
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 等环境中为 {iInt}。为什么 Erg 采用前者的语法?
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 中,运算符使你可以在不太注意错误的情况下编写。
```erg
read_file!() =
f = open!("foo.txt")? # 失敗したらエラーをすぐさま返すので、fはFile型
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并且原则上禁止多重和多层继承因此继承的使用相对安全。
## 为什么多相关数的子类型推理默认指向记名特雷特?
默认情况下,指向结构托盘会使类型指定变得复杂,并且可能会混合程序员的非预期行为。
```erg
# If T is a subtype of a structural trait...
# f: |T <: Structural Trait {.`_+_` = Self.(Self) -> Self; .`_-_` = Self.(Self) -> Self}| (T, T) -> T
f|T| x, y: T = x + y - x
# T is a subtype of a nominal trait
# 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 试图用类来控制一切一样。