Retranslate zh_CN and zh_TW doc

This commit is contained in:
Cai Bingjun 2022-09-04 10:47:30 +08:00
parent a711efa99b
commit c5fba46ee0
355 changed files with 4129 additions and 16617 deletions

View file

@ -1,4 +1,4 @@
# 内置常量
# built-in constants
## True
@ -8,6 +8,6 @@
## Ellipsis
## NotImplemented
## Not Implemented
## Inf
## Inf

View file

@ -1,17 +1,17 @@
# 功能
# functions
## 基本功能
## basic functions
### if|T; U|(cond: Bool, then: T, else: U) -> T or U
### map|T; U|(i: Iterable T, f: T -> U) -> Map U
请注意,参数的顺序与 Python 相反
Note that the order of arguments is reversed from Python.
### log(x: Object, type: LogType = Info) -> None
在调试显示中记录“x”。 执行完成后汇总并显示日志
支持表情符号的终端根据“类型”添加前缀
Log `x` in debug display. Logs are summarized and displayed after the execution is finished.
Emoji-capable terminals are prefixed according to `type`.
* type == Info: 💬
* type == Ok: ✅
@ -20,17 +20,17 @@
### panic(msg: Str) -> Panic
显示msg并停止。
支持表情符号的终端有一个🚨前缀。
Display msg and stop.
Emoji-capable terminals have a 🚨 prefix.
### discard|T|(x: ...T) -> NoneType
扔掉`x`。不使用返回值时使用。与 `del` 不同,它不会使变量 `x` 不可访问
Throw away `x`. Used when the return value is not used. Unlike `del`, it does not make the variable `x` inaccessible.
```erg
p! x =
# q!应该返回一些不是None或()的值
# 如果不需要,请使用`discard`
``` erg
p!x=
# Let q! return some None or non-() value
# use `discard` if you don't need it
discard q!(x)
f x
@ -40,32 +40,32 @@ assert True # OK
### import(path: Path) -> Module or CompilerPanic
导入一个模块。如果找不到模块,则引发编译错误
Import a module. Raises a compilation error if the module is not found.
### eval(code: Str) -> Object
`code`作为代码进行评估并返回。
Evaluate code as code and return.
### classof(object: Object) -> Class
返回`object`的类。
但是,由于无法比较类,如果要判断实例,请使用`object in Class`而不是`classof(object) == Class`
编译时确定的结构类型是通过`Typeof`获得的
Returns the class of `object`.
However, since classes cannot be compared, use `object in Class` instead of `classof(object) == Class` if you want to judge instances.
The structure type determined at compile time is obtained with `Typeof`.
## Iterator, Array生成系统
## Iterator, Array generation system
### repeat|T|(x: T) -> RepeatIterator T
```erg
``` erg
rep = repeat 1 # Repeater(1)
for! rep, i =>
print! i
print!i
# 1 1 1 1 1 ...
```
### dup|T; N|(x: T, N: Nat) -> [T; N]
```erg
``` erg
[a, b, c] = dup new(), 3
print! a # <Object object>
print! a == b # False
@ -73,21 +73,21 @@ print! a == b # False
### cycle|T|(it: Iterable T) -> CycleIterator T
```erg
``` erg
cycle([0, 1]).take 4 # [0, 1, 0, 1]
cycle("hello").take 3 # "hellohellohello"
```
## 定数式関数
## constant expression functions
### Class
创建一个新类。 与`Inherit`不同,通过`Class`传递与基类型无关,并且方法会丢失
您将无法进行比较,但您可以进行模式匹配等操作
Create a new class. Unlike `Inherit`, passing through `Class` is independent of the base type and methods are lost.
You won't be able to compare, but you can do things like pattern matching.
```erg
``` erg
C = Class {i = Int}
NewInt = Class Int
NewInt = ClassInt
Months = Class 1..12
jan = Months.new(1)
jan + Months.new(2) # TypeError: `+` is not implemented for 'Months'
@ -96,26 +96,26 @@ match jan:
_ -> log "Other"
```
第二个参数 Impl 是要实现的特征
The second argument, Impl, is the trait to implement.
### Inherit
继承一个类。您可以按原样使用基类方法
Inherit a class. You can use the base class methods as they are.
### Trait
### Traits
创造一个新的特质。目前,只能指定记录类型
Create a new trait. Currently, only record types can be specified.
### Typeof
### Type of
返回参数类型。如果要获取运行时类,请使用`classof`
如果您将其用于类型规范,则会出现警告。
Returns the argument type. Use `classof` if you want to get the runtime class.
If you use it for type specification, Warning will appear.
```erg
x: Typeof i = ...
``` erg
x: Type of i = ...
# TypeWarning: Typeof(i) == Int, please replace it
```
### Deprecated
作为解码器使用。警告不推荐使用的类型或函数
Use as a decorator. Warn about deprecated types and functions.

View file

@ -1,57 +1,42 @@
# alstruct
# alstructuration
Modules qui fournissent des caractères représentant les structures et les parcelles d'algèbre.
提供表示代数结构的托盘和相应补丁的模块。
* member
- membres membres membres membres membres
## binop
BinOp Op: Kind 2 = Subsume Op(Self, Self.ReturnTypeOf Op), Additional: {
.ReturnTypeof = TraitType -&gt; Type
}
Nat &lt;: BinOp Add
assert Nat. ReturnTypeof(Add) == Nat
assert Nat. ReturnTypeof(Sub) == Int
assert Nat. ReturnTypeof(Mul) == Nat
assert Nat.ReturnTypeof(Div) == Positive Ratio
``` erg
Kind 2 = Subsume Op(Self, Self. returntypeof Op) Additional: {
.ReturnTypeof = TraitType -> Type
}
## semi-groupe
SemiGroup Op: Kind 2 = Op(Self, Self)
IntIsSemiGroupAdd = Patch Int, Impl=SemiGroupAdd
Int &lt;: SemiGroup Add
Nat <: BinOp Add
assert Nat. returntypeof (Add) == Nat
assert Nat.ReturnTypeof(Sub) == Int
assert Nat. returntypeof (Mul) == Nat
assert Nat.ReturnTypeof(Div) == Positive Ratio
```
## amateurs
## * Identity law: x.map(id) == x
## * Composition law: x.map(f).map(g) == x.map(f.then g)
Functor = Trait {
.map|T, U: Type| = (Self(T), T -&gt; U) -&gt; Self U
}
## semigroup
## Application
## * Identity law: x.app(X.pure(id)) == x
Applicative = Subsume Functor, Additional: {
.pure|T: Type| = T -&gt; Self T
.app|T, U: Type| = (Self(T), Self(T -&gt; U)) -&gt; Self U
}
``` erg
SemiGroup Op: Kind 2 = Op(Self, Self)
## monad monad
Monad = Subsume Applicative, Additional: {
.bind|T, U: Type| = (Self(T), T -&gt; Self U) -&gt; Self U
}
IntIsSemiGroupAdd = Patch Int, Impl=SemiGroup Add
Int <: SemiGroup Add
```
## functor
``` erg
## * Identity law: x.map(id) == x
## * Composition law: x.map(f).map(g) == x.map(f.then g)
Functor = Trait {
. map | t, u: type | = (self (t), t - > u) - > self u
}
```
## applicative
``` erg
## * Identity law: x.app(x. pure(id)) == x
Applicative = Subsume Functor, Additional: {
t: . pure | type | = t - > self t
. app | t, u: type | = (self (t), self (t - > u)) - > self u
}
```
## monad
``` erg
Monad = Subsume Applicative, Additional: {
. bind | t, u: type | = (self (t), t - > self u) - > self u
}
```

View file

@ -1,24 +1,24 @@
# module `repl`
provides REPL(Read-Eval-Print-Loop)-related APIs
provides REPL(Read-Eval-Print-Loop)-related APIs.
## functions
* ` gui _ help `
* `gui_help`
在浏览器中显示关于对象的信息。离线也可以使用。
View information about an object in a browser. Can be used offline.
## types
### Guess = Object
## ## methods
#### methods
* * ` . guess `
* `.guess`
根据所给出的自变量和返回值来推测函数。
Infers a function given its arguments and return value.
``` erg
guess((1) 2) # <int. __add__method=""></int.>
[1, 2] . guess(3、4),[1,2,3,4])# < array (t, n) . concat method >
1.guess((1,), 2) # <Int.__add__ method>
[1, 2].guess((3, 4), [1, 2, 3, 4]) # <Array(T, N).concat method>
```

View file

@ -1,6 +1,6 @@
# module `status`
定义了表示状态的类型。请根据情况排除选项使用。
A type is defined to represent the state. Please use it by removing the option according to the situation.
* ExecResult ={“success”“warning”“failure”“fatal”“unknown”}
ExecStatus ={“ready”“running”“sleeping”“plague”“completed”“terminated”}
* ExecResult = {"success", "warning", "failure", "fatal", "unknown"}
* ExecStatus = {"ready", "running", "sleeping", "plague", "completed", "terminated"}

View file

@ -1,59 +1,59 @@
# module `unit`
`unit`模块是将数值计算中常用的单位定义为型的模块。
Erg的数值型有`Nat` `Int` `Ratio`等。但是,这些模型并没有掌握“这意味着什么”的信息,只能进行米和码之间的加法等荒唐的计算。
通过使用`unit`模块,可以防止将单位不同的数值传递给函数的错误。
这样的失误是实际发生,而且[单位系的错误火星探测器失踪](http://www.sydrose.com/case100/287/)等,可能引起严重的bug。
如果想在进行数值计算的基础上提高代码的鲁棒性的话应该事先使用这个模块。
The `unit` module is a module that defines units that are often used in numerical calculations as types.
Erg numeric types include `Nat`, `Int`, `Ratio`, and so on. However, these types do not have information about "what the numbers mean", so nonsense calculations such as adding meters and yards can be performed.
By using the `unit` module, you can avoid mistakes such as passing numbers with different units to functions.
Mistakes like this actually occur, and serious bugs such as [Mars probe missing due to wrong unit system](http://www.sydrose.com/case100/287/) can cause it.
You should use this module if you want your code to be more robust when doing numerical computations.
``` erg
{*} = import "unit"
等价于x = 6m# `x = Meter.new(6)`
等价于t = 3s# `t = c.new(3)`
# m/s是速度的单位对象Velocity型
print !x/ t# 2m/s
print !x + 4m# 10m
print !x + 2s# TypeError: `+`(Meter, Sec) is not implemented
x = 6m # equivalent to `x = Meter.new(6)`
t = 3s # equivalent to `t = Sec.new(3)`
# m/s is a velocity unit object, of type Velocity
print! x/t # 2m/s
print! x + 4m # 10m
print! x + 2s # TypeError: `+`(Meter, Sec) is not implemented
```
`m` `s` `m/s`这样的对象被称为单位对象。它本身就有1m, 1s, 1m/s的意思。`m/s`可以说是m和s的合成产生的单位对象。
The objects `m`, `s`, and `m/s` are called unit objects. It has the meaning of 1m, 1s, 1m/s by itself. `m/s` can be said to be a unit object created by combining m and s.
unit将以下单位定义为型。国际单位制(SI)。
In unit, the following units are defined as types. It is called SI (International System of Units).
* 长度:Meter(单位常数:m)
* 质量:KiloGram(单位常数:kg, g = 0.001kg)
* 时间:Sec(分钟、时间、日、年等有由Sec生成的minute, hour, day, year等常数)
* 电流:Amper(单位常数:a)
* 温度:Kelvin(单位常数:k, Fahren也有Celsius型可相互转换)
* 物质的量:Mol(单位常数:Mol)
* 光度:Candela(单位常数:cd)
* Length: Meter (unit constant: m)
* Mass: KiloGram (unit constant: kg, g = 0.001kg)
* Time: Sec (minute, hour, day, year, etc. have constants such as minute, hour, day, year generated from Sec)
* Current: Amper (unit constant: a)
* Temperature: Kelvin (unit constant: k, Fahren, Celsius types are also available and can be converted to each other)
* Amount of substance: Mol (unit constant: mol)
* Luminous intensity: Candela (unit constant: cd)
另外,`Unit1` `UnitMul` `UnitDiv`这样的类型被定义,使用这个可以合成基本类型创建新的单位。
例如,振动频率的单位赫兹(hertz)是用振动周期(秒)的倒数来定义的,所以`UnitDiv(Unit1, Sec)`
想要把这个类型视为有意义的类型(想要加上专用的方法,等等)的时候,[补丁](./../ . ./syntax/type/07_patch.md)。
In addition, the types `Unit1`, `UnitMul`, and `UnitDiv` are defined, which can be used to create new units by combining basic types.
For example, `UnitDiv(Unit1, Sec)`, because the unit of frequency hertz (hertz) is defined as the reciprocal of the vibration period (seconds).
If you want to treat this type as a meaningful type (such as adding a dedicated method), you should create a [patch](./../../syntax/type/07_patch.md).
``` erg
Hertz = Patch UnitDiv(Unit1, Sec)
SquareMeter = UnitMul(Meter, Meter)
SquareMeter = Patch UnitMul(Meter, Meter)
```
辅助单位也被预先定义了几个。
Some auxiliary units are also predefined.
* 振动频率:Hertz(hz)
* 力:Newton。
* 能量:Joule(j)
* 工作量:Watt(w)
* 电势:Volt(v)
* 电阻:Ohm(Ohm)
* 速度:Velocity(m/s)
* 面积:SquareMeter(m**2)
* 体积:CubicMeter(m**3) (litre = 10e- 3m **3)
* 角度:Degree(deg) (rad = 180/pi deg)
* 长度:Feet, Yard, Inch, Mile, Ly, Au, Angstrom
* 重量:Pond
* Frequency: Hertz(hz)
* Force: Newton(newton)
* Energy: Joule(j)
* Power: Watt(w)
* Potential: Volt(v)
* Electrical resistance: Ohm(ohm)
* Velocity: Velocity(m/s)
* Area: SquareMeter(m**2)
* Volume: CubicMeter(m**3) (liter = 10e-3 m**3)
* Angle: Degree(deg) (rad = 180/pi deg)
* Length: Feet, Yard, Inch, Mile, Ly, Au, Angstrom
* Weight: Pound
另外,前缀也有定义。
It also defines a prefix.
* Femto = 1e-15
* Pico = 1e-12
@ -68,6 +68,6 @@ SquareMeter = UnitMul(Meter, Meter)
* Giga = 1e+9
* Tera = 1e+12
* Peta = 1e+15
* Exa = 1e+18
*Exa = 1e+18
※与名字的由来相反Erg基本上采用MKS单位制。cgs单位系unit模块的希望时,外部库([cgs] (https://github.com/mtshiba/cgs)等),请使用。
*Contrary to the origin of the name, Erg basically adopts the MKS unit system. If you want the unit module of the CGS unit system, please use an external library ([cgs](https://github.com/mtshiba/cgs) etc.).

View file

@ -1,24 +1,24 @@
# module `unsound`
提供的api执行在Erg的类型系统中无法保证安全的不健全和不安全的操作。
Provides APIs perform unsound and unsafe operations that cannot be guaranteed safe in Erg's type system.
## `unsafe!`
执行一个`Unsafe`过程。就像Rust一样`Unsafe`的api不能被直接调用而是全部作为高阶函数传递给这个过程。
Executes an `Unsafe` procedure. Just like Rust, `Unsafe` APIs cannot be called directly, but are all passed as higher-order functions to this procedure.
``` erg
unsound = import "unsound"
i = unsound.unsafe!do !:
# convert `Result Int` to `Int`
unsound.transmute input !() . try into (int), int
i = unsound. unsafe! do!:
# convert `Result Int` to `Int`
unsound.transmute input!().try_into(Int), Int
```
## transmute
## transmit
将第一个参数的对象转换成第二个参数的类型。不进行模板检查。
这个函数损害型系统的型安全性。使用的时候请进行验证等。
Converts the object of the first argument to the type of the second argument. No type checking is done.
This function breaks the type safety of the type system. Please perform validation before using.
## auto_transmute
`transmute`不同自动转换为期待的类型。与Ocaml的`Obj.magic`作用相同。
Unlike `transmute`, it automatically converts to the expected type. Works the same as Ocaml's `Obj.magic`.

View file

@ -1,64 +1,64 @@
# 运算符
# operator
## 中缀运算符
## infix operator
### `_+_`|R; O; A <: Add(R, O)|(x: A, y: R) -> O
执行加法。
Perform addition.
### `_-_`|R; O; S <: Sub(R, O)|(x: S, y: R) -> O
执行减法。
Perform subtraction.
### `*`|R; O; M <: Mul R, O|(x: M, y: R) -> O
执行乘法。
Perform multiplication.
### `/`|R; O; D <: Div(R, O)|(x: D, y: R) -> O
进行除法。
Perform division.
## 中缀字母运算符
## infix alphabet operator
### `and`(x: Bool, y: Bool) -> Bool
执行 and 操作。
Executes the and operation.
### `or`(x: Bool, y: Bool) -> Bool
执行 and 操作。
Executes the and operation.
## 前缀运算符
## prefix operator
### `+_`|T <: Num|(x: T) -> T
默认与 id 相同。
Same as id by default.
### `-_`|T <: Num|(x: T) -> T.Neg
例如 Nat.`-`: Nat -> Neg 和返回值不同。
For example, Nat.`-`: Nat -> Neg and the return value is different.
### `!`|T <: Immut|(x: T) -> `T!`
从不可变对象创建可变对象。
该运算符本身不是程序性的,可以在函数内部使用。
Create a mutable object from an immutable object.
This operator itself is not procedural and can be used inside a function.
### `..`|T <: Ord|(x: T) -> Range T
在 x 的末尾创建一个没有下限的 Range 对象。
x..x 仅返回 x 作为迭代器。
Creates a Range object with no lower bound at the end of x.
x..x returns only x as an iterator.
### `..<`|T <: Ord|(x: T) -> Range T
x..<x 产生一个空的 Range 对象不产生任何迭代器
x..<x results in an empty Range object, yielding nothing as an iterator.
## 后缀运算符
## postfix operator
解析中缀运算符失败时调用后缀运算符。
也就是说,即使`x..`返回一个函数,`x..y``(..)(x, y)`而不是`(x..)(y)`
A postfix operator is called when parsing a parsing infix operator fails.
That is, even if `x..` returns a function, `x..y` is `(..)(x, y)` and not `(x..)(y)`.
### |T <: Ord|(x: T)`..` -> Range T
创建一个从 x 开始没有上限的 Range 对象。
Creates a Range object with no upper bound starting at x.
### |T <: Ord|(x: T)`<..` -> Range T

View file

@ -1,34 +1,34 @@
# 过程
# procedures
## print!
``` erg
打印x->无类型
print!(x) -> NoneType
```
使用换行符返回 x。
Returns x with a newline.
##调试&排除;
##debug&excl;
``` erg
调试x类型=信息)-> NoneType
debug!(x, type = Info) -> NoneType
```
用换行符调试 x文件名、行号、变量名一起显示。 在发布模式中删除。
支持表情符号的终端根据类型加前缀。
Debug x with newline (file name, line number, variable name is displayed together). Removed in release mode.
Emoji-capable terminals are prefixed according to type.
* type == Info: 💬
* type == Ok: ✅
* type == Warn: ⚠️
* type == Hint: 💡
## for!i: Iterable T, block: T => NoneType
## for! i: Iterable T, block: T => NoneType
以块的动作遍历迭代器。
Traverse the iterator with the action of block.
## while!cond: Bool!, block: () => NoneType
## while! cond: Bool!, block: () => NoneType
当cond为True时的执行块。
Execute block while cond is True.
## Lineno!() -> Nat

View file

@ -1,109 +1,109 @@
# 特殊形式
# Special form
特殊形式是不能在 Erg 类型系统中表达的运算符、子程序(等等)。它被`包围,但实际上无法捕获。
此外为方便起见还出现了“Pattern”、“Body”和“Conv”等类型但不存在此类类型。它的含义也取决于上下文。
Special forms are operators, subroutines (and the like) that cannot be expressed in the Erg type system. It is surrounded by ``, but it cannot actually be captured.
Also, types such as `Pattern`, `Body`, and `Conv` appear for convenience, but such types do not exist. Its meaning also depends on the context.
## `=`(pat: Pattern, body: Body) -> NoneType
将 body 分配给 pat 作为变量。如果变量已存在于同一范围内或与 pat 不匹配,则引发错误。
它还用于记录属性定义和默认参数。
Assign body to pat as a variable. Raise an error if the variable already exists in the same scope or if it doesn't match pat.
It is also used in record attribute definitions and default arguments.
```erg
``` erg
record = {i = 1; j = 2}
f(x: Int, y = 2) = ...
```
当主体是类型或函数时,`=` 具有特殊行为。
左侧的变量名嵌入到右侧的对象中。
`=` has special behavior when the body is a type or a function.
The variable name on the left side is embedded in the object on the right side.
```erg
``` erg
print! Class() # <class <lambda>>
print! x: Int -> x + 1 # <function <lambda>>
C = Class()
print! c # <class C>
f = x: Int -> x + 1
print! f # <function f>
g x: Int = x + 1
gx: Int = x + 1
print! g # <function g>
K X: Int = Class(...)
KX: Int = Class(...)
print! K # <kind K>
L = X: Int -> Class(...)
print! L # <kind L>
```
`=` 运算符的返回值为“未定义”。
函数中的多个赋值和 `=` 会导致语法错误。
The `=` operator has a return value of "undefined".
Multiple assignments and `=` in functions result in syntax errors.
```
i = j = 1 # SyntaxError: 不允许多次赋值
``` erg
i = j = 1 # SyntaxError: multiple assignments are not allowed
print!(x=1) # SyntaxError: cannot use `=` in function arguments
# 提示:您的意思是关键字参数(`x: 1`)吗?
# hint: did you mean keyword arguments (`x: 1`)?
if True, do:
i = 0 # SyntaxError: 块不能被赋值表达式终止
i = 0 # SyntaxError: A block cannot be terminated by an assignment expression
```
## `->`(pat: Pattern, body: Body) -> Func
生成匿名函数,函数类型。
Generate anonymous functions, function types.
## `=>`(pat: Pattern, body: Body) -> Proc
生成匿名过程,过程类型。
Generate anonymous procedure, procedure type.
## `:`(subject, T)
确定主题是否与 T 匹配。如果它们不匹配,则抛出编译错误。
Determine if subject matches T. If they don't match, throw a compile error.
```erg
``` erg
a: Int
f x: Int, y: Int = x / y
```
也用于 `:` 应用样式。
Also used for `:` applied styles.
```erg
f x:
``` erg
fx:
y
z
```
`:``=`一样,运算的结果是不确定的。
Like `:` and `=`, the result of the operation is undefined.
```erg
_ = x: Int # 语法错误:
print!(x: Int) # 语法错误:
``` erg
_ = x: Int # SyntaxError:
print!(x: Int) # SyntaxError:
```
## `.`(obj, attr)
读取obj的属性。
`x.[y, z]` 将 x 的 y 和 z 属性作为数组返回。
Read attributes of obj.
`x.[y, z]` will return the y and z attributes of x as an array.
## `|>`(obj, c: Callable)
执行`c(obj)``x + y |>.foo()``(x + y).foo()` 相同。
Execute `c(obj)`. `x + y |>.foo()` is the same as `(x + y).foo()`.
### (x: Option T)`?` -> T | T
### (x: Option T)`?` -> T | T
后缀运算符。如果出现错误,请立即调用 `x.unwrap()``return`
Postfix operator. Call `x.unwrap()` and `return` immediately in case of error.
## match(obj, ...lambdas: Lambda)
对于 obj执行与模式匹配的 lambda。
For obj, execute lambdas that match the pattern.
```erg
match [1, 2, 3]:
``` erg
match[1, 2, 3]:
(l: Int) -> log "this is type of Int"
[[a], b] -> log a, b
[...a] -> log a
# (1, 2, 3)
# (one two three)
```
## del(x: ...T) -> NoneType | T
删除变量“x”。但是无法删除内置对象。
Delete the variable `x`. However, built-in objects cannot be deleted.
```erg
``` erg
a = 1
del a # OK
@ -112,48 +112,48 @@ del True # SyntaxError: cannot delete a built-in object
## do(body: Body) -> Func
生成一个不带参数的匿名函数。 `() ->` 的语法糖。
Generate an anonymous function with no arguments. Syntactic sugar for `() ->`.
## do!(body: Body) -> Proc
生成不带参数的匿名过程。 `() =>` 的语法糖。
Generate an anonymous procedure with no arguments. Syntactic sugar for `() =>`.
## `else`(l, r) -> Choice
创建一个由两对组成的类元组结构,称为 Choice 对象。
`l, r` 被懒惰地评估。也就是说,只有在调用 .get_then 或 .get_else 时才会计算表达式。
Creates a tuple-like structure of two pairs called Choice objects.
`l, r` are evaluated lazily. That is, the expression is evaluated only when `.get_then` or `.get_else` is called.
```erg
``` erg
choice = 1 else 2
assert choice.get_then() == 1
assert choice.get_else() == 2
assert True.then(choice) == 1
```
## 集合运算符
## set operator
### `[]`(...objs)
从参数创建一个数组或从可选参数创建一个字典。
Creates an array from arguments or a dict from optional arguments.
### `{}`(...objs)
从参数创建一个集合。
Create a set from arguments.
### `{}`(...fields: ((Field, Value); N))
生成记录。
Generate a record.
### `{}`(layout, ...names, ...preds)
生成筛型等级2型。
Generates sieve type, rank 2 type.
### `...`
展开嵌套集合。它也可以用于模式匹配。
Expand a nested collection. It can also be used for pattern matching.
``` erg
[x, ...y] = [1, 2, 3]
[x,...y] = [1, 2, 3]
assert x == 1 and y == [2, 3]
assert [x, ...y] == [1, 2, 3]
assert [...y, x] == [2, 3, 1]
@ -162,14 +162,14 @@ assert x == 1 and yz == {y = 2; z = 3}
assert {x; ...yz} == {x = 1; y = 2; z = 3}
```
## 虚拟运算符
## virtual operator
用户不能直接使用的运算符。
Operators that cannot be used directly by the user.
### ref(x: T) -> Ref T | T
返回对对象的不可变引用。
Returns an immutable reference to the object.
### ref!(x: T!) -> Ref!T! | T!
### ref!(x: T!) -> Ref! T! | T!
返回对可变对象的可变引用。
Returns a mutable reference to a mutable object.

View file

@ -1,90 +1,90 @@
# 内置 Erg 类型列表
# List of built-in Erg types
类型本身的属性不存储在 `.__dict__` 中,不能从实例中引用
Attributes of the type itself are not stored in the `.__dict__` and cannot be referenced from the instance
## 基本类型
## Fundamental types
### 对象
### Objects
* `__dir__`将对象的属性作为数组返回dir函数
* `__getattribute__`: 获取并返回一个属性
* `__hash__`:返回对象的哈希值
* `__repr__`:对象的字符串表示(不存在丰富/默认实现)
* `__sizeof__`:返回对象的大小(包括在堆中分配的大小)
* `__dir__`: Returns the attributes of the object as an array (dir function)
* `__getattribute__`: get and return an attribute
* `__hash__`: returns the hash value of the object
* `__repr__`: string representation of the object (not rich/default implementation exists)
* `__sizeof__`: returns the size of the object (including the size allocated in the heap)
### 显示
### Show
* `__str__`:返回对象的字符串表示(丰富)
* `__str__`: returns the string representation (rich) of the object
### Fmt
###Fmt
* `__format__`: 返回一个格式化的字符串
* `__format__`: Returns a formatted string
### 文档
### Doc
* `__doc__`:对象描述
* `__doc__`: object description
### 命名
### Named
* `__name__`: 对象的名称
* `__name__`: the name of the object
### 泡菜
### Pickles
* `__reduce__`: 用 Pickle 序列化对象
* `__reduce_ex__`: __reduce__ 允许你指定协议版本
* `__reduce__`: Serialize objects with Pickle
* `__reduce_ex__`: __reduce__ that allows you to specify the protocol version
## 对象系统
## Object system
Trait 类相当于 Python 中的 ABC抽象基类接口
实例属于1、True、“aaa”等。
类是 Int、Bool、Str 等。
Trait class is equivalent to ABC (abstract base class, interface) in Python
Instance belongs to 1, True, "aaa", etc.
Class is Int, Bool, Str, etc.
### 类型
### Type
* `__supers__`:超类型(`__mro__` 是一个数组,但这个是一个 Set
* `__supers__`: Supertypes (`__mro__` is an array, but this one is a Set)
* `__basicsize__`:
* `__dictoffset__`Evm 不支持
* `__dictoffset__`: not supported by Evm
* `__flags__`:
* `__itemsize__`:实例的大小(如果不是类,则为 0
* `__weakrefoffset__`Evm 不支持
* `__membercheck__`: 相当于`ismember(x, T)`
* `__subtypecheck__`:等价于`issubtype(U, T)`,别名`__subclasshook__`兼容CPython
* `__itemsize__`: Size of instance (0 if not Class)
* `__weakrefoffset__`: not supported by Evm
* `__membercheck__`: equivalent to `ismember(x, T)`
* `__subtypecheck__`: Equivalent to `issubtype(U, T)`, with alias `__subclasshook__` (compatible with CPython)
### 实例
### Instances
* `__class__`:返回创建实例的类(自动附加到使用 `.new` 创建的对象)
* `__class__`: Returns the class from which the instance was created (automatically attached to objects created with `.new`)
### Class
* `__mro__`:用于方法解析的类型数组(包括自身,始终以 Object 结尾)
* `__base__`:基本类型(`__mro__[1]` 如果有多个)
* `__new__`: 实例化
* `__init__`: 初始化实例
* `__init_subclass__`: 初始化实例
* `__intstancecheck__`:使用类似于 `MyClass.__instancecheck__(x)`,等价于 `isinstance(x, MyClass)`
* `__subclasscheck__`:等价于 `issubclass(C, MyClass)`
* `__mro__`: Type array for method resolution (includes itself, always ends with Object)
* `__base__`: base type (`__mro__[1]` if there are multiple)
* `__new__`: instantiate
* `__init__`: Initialize the instance
* `__init_subclass__`: Initialize the instance
* `__intstancecheck__`: use like `MyClass.__instancecheck__(x)`, equivalent to `isinstance(x, MyClass)`
* `__subclasscheck__`: equivalent to `issubclass(C, MyClass)`
## 运算符
## operator
此处指定以外的运算符没有特殊类型
Operators other than those specified here have no special types
### 方程
### Eq
* `__eq__(self, rhs: Self) -> Bool`: 对象比较函数 (==)
* `__ne__`: 对象比较函数 (!=),默认实现
* `__eq__(self, rhs: Self) -> Bool`: object comparison function (==)
* `__ne__`: object comparison function (!=), with default implementation
### 秩序
### Ord
* `__lt__(self, rhs: Self) -> Bool`: 对象比较函数 (<)
* `__le__`:对象比较函数(<=),默认实现
* `__gt__`:对象比较函数(>),默认实现
* `__ge__`:对象比较函数(>=),默认实现
* `__lt__(self, rhs: Self) -> Bool`: Object comparison function (<)
* `__le__`: object comparison function (<=), with default implementation
* `__gt__`: object comparison function (>), with default implementation
* `__ge__`: object comparison function (>=), with default implementation
### BinAdd
### Bin Add
* 实现 `__add__(self, rhs: Self) -> Self`: `+`
* Implements `__add__(self, rhs: Self) -> Self`: `+`
### 添加R
### Add R
* `__add__(self, rhs: R) -> Self.AddO`
@ -98,93 +98,93 @@ Trait 类相当于 Python 中的 ABC抽象基类接口
### BinMul <: Mul Self
* `__pow__`:实现 `**`(默认实现)
* `__pow__`: implements `**` (with default implementation)
### Div R, O
* 实现 `__div__(self, rhs: Self) -> Self`: `/`,可能会因为 0 而恐慌
* Implements `__div__(self, rhs: Self) -> Self`: `/`, may panic due to 0
### BinDiv <: Div Self
* `__mod__`: 实现 `%` (默认实现)
* `__mod__`: implement `%` (with default implementation)
## 数值型
## numeric type
### Num (= Add and Sub and Mul and Eq)
例如除了ComplexVector、Matrix和Tensor都是NumMatrix和Tensor中的*分别与dot和product相同
As an example other than Complex, Vector, Matrix, and Tensor are Num (* in Matrix and Tensor are the same as dot and product, respectively)
### Complex (= Inherit(Object, Impl := Num))
* `imag: Ratio`:返回虚部
* `real: Ratio`:返回实部
* `conjugate self -> Complex`:返回复共轭
* `imag: Ratio`: returns the imaginary part
* `real: Ratio`: returns the real part
* `conjugate self -> Complex`: returns the complex conjugate
### Float (= Inherit(FloatComplex, Impl := Num))
### Ratio (= Inherit(Complex, Impl := Num))
* `numerator: Int`: 返回分子
* `denominator: Int`: 返回分母
* `numerator: Int`: returns the numerator
* `denominator: Int`: Returns the denominator
### Int (= Inherit Ratio)
### Nat (= Inherit Int)
* `times!`: 运行 proc self 时间
* `times!`: run the proc self times
## 其他基本类型
## Other basic types
### 布尔值
### Bool
* `__and__`:
* `__or__`:
* `not`:
## 字符串 (<: 序列)
## Str (<: Seq)
* `capitalize`
* `chomp`: 删除换行符
* `chomp`: remove newline characters
* `isalnum`:
* `isascii`:
* `isalpha`:
* `isdecimal`:
* `isdight`:
* `isidentifier`
* `islower`
* `isnumeric`
* `is sight`:
* `is identifier`
*`islower`
* `is numeric`
* `isprintable`
* `isspace`
* `istitle`
* `is title`
* `isupper`
* `lower`
*`lower`
* `swapcase`
* `title`
* `upper`
其他
## others
###
### Bits
* `from_bytes`:从字节转换
* `to_bytes`:转换为字节(指定长度和字节序(字节序))
* `bit_length`:返回位长度
* `from_bytes`: Convert from Bytes
* `to_bytes`: Convert to Bytes (specify length and endian (byteorder))
* `bit_length`: returns bit length
### 可迭代 T
### Iterable T
请注意,它不是 `Iterator` 本身的类型。 `Nat``Iterable` 但你不能 `Nat.next()`,你需要 `Nat.iter().next()`
Note that it is not the type of `Iterator` itself. `Nat` is `Iterable` but you can't `Nat.next()`, you need to `Nat.iter().next()`.
* `iter`:创建一个迭代器。
* `iter`: Create an Iterator.
### 迭代器 T
### Iterator T
Nat 和 Range 有迭代器,所以 `Nat.iter().map n -> n**2`, `(3..10).iter().fold (sum, n) -> sum + n*2`等是可能的。
由于所有和任何在使用后都会被破坏,因此没有副作用。这些应该使用没有副作用的 `next` 来实现,但内部使用 `Iterator!.next!` 来提高执行效率。
Nat and Range have Iterators, so `Nat.iter().map n -> n**2`, `(3..10).iter().fold (sum, n) -> sum + n*2` etc. are possible.
Since all and any are destroyed after use, there are no side effects. These are supposed to be implemented using `next` which has no side effects, but internally `Iterator!.next!` is used for execution efficiency.
* `next`:返回第一个元素和剩余的迭代器。
* `all`
* `any`
* `filter`
* `next`: Returns the first element and the remaining Iterator.
*`all`
*`any`
*`filter`
* `filter_map`
* `find`
* `find_map`
@ -192,21 +192,21 @@ Nat 和 Range 有迭代器,所以 `Nat.iter().map n -> n**2`, `(3..10).iter().
* `flatten`
* `fold`
* `for_each`
* `map`
*`map`
* `map_while`
* `nth`
* `pos`
*`pos`
* `take`
* `unzip`
* `zip`
*`zip`
### Iterator!T = IteratorT ...
### Iterator!T = IteratorT and ...
* `next!`:获取第一个元素。
* `next!`: Get the first element.
## SizedIterator T = 迭代器 T 和 ...
## SizedIterator T = Iterator T and ...
有限数量元素的迭代器。
An Iterator over a finite number of elements.
* `len`:
* `chain`:
@ -221,42 +221,42 @@ Nat 和 Range 有迭代器,所以 `Nat.iter().map n -> n**2`, `(3..10).iter().
* `max`:
* `min`:
## Seq T = SizedIterable T ...
## Seq T = SizedIterable T and ...
* `concat`: 合并两个 Seq
* `__getitem__`:等同于使用 `[]` 访问(否则会出现恐慌)
* `get`: __getitem__ 不同,它返回 Option
* `maketrans`:创建替换表(静态方法)
* `replace`: 替换
* `translate`:根据替换表替换
* `insert`: 添加到 idx
* `remove`: 删除 idx
* `prepend`: 前置
* `dequeue`: 移除头部
* `push`:添加到末尾
* `pop`: 取尾巴
* `dedup`:删除连续值
* `uniq`:删除重复元素(通过 sort |> dedup 实现,因此顺序可能会改变)
* `swap`:交换元素
* `reverse`:反转元素
* `sort`: 排序元素
* `concat`: Combine two Seqs
* `__getitem__`: Equivalent to accessing with `[]` (otherwise panics)
* Unlike `get`: __getitem__, it returns Option
* `maketrans`: Create a replacement table (static method)
* `replace`: replace
* `translate`: replace according to the replacement table
* `insert`: Add to idx
* `remove`: remove idx
* `prepend`: prepend
* `dequeue`: remove the head
* `push`: added to the end
* `pop`: take the tail
* `dedup`: remove consecutive values
* `uniq`: Remove duplicate elements (implemented by sort |> dedup, so order may change)
* `swap`: Swap elements
* `reverse`: reverse elements
* `sort`: sort elements
* `first`:
* `last`:
### Seq!T (= Seq T and ...)
### Seq! T (= Seq T and ...)
* `__setitem__!`:
* `__delitem__!`:
* `插入!`:添加到 idx
* `remove!`: 删除 idx
* `prepend!`:前置
* `dequeue!`: 删除开头
* `push!`:添加到末尾
* `pop!`:拿尾巴
* `dedup!`:删除连续值
* `uniq!`: 删除重复元素(通过排序实现!|> dedup!,因此顺序可能会改变)
* `swap!`:交换元素
* `reverse!`:反转元素
* `insert!`: Add to idx
* `remove!`: remove idx
* `prepend!`: prepend
* `dequeue!`: remove the beginning
* `push!`: added to the end
* `pop!`: take the tail
* `dedup!`: remove consecutive values
* `uniq!`: Remove duplicate elements (implemented by sort! |> dedup!, so order may change)
* `swap!`: swap elements
* `reverse!`: reverse the element
* `set!`
* `sort!`: 排序元素
* `sort!`: sort elements
* `translate!`

View file

@ -1,3 +1,4 @@
# Array! T
表示可变长度数组的类型。在编译时长度未知时使用。 有一个语法糖叫做` [t]!`。在`Array! T = ArrayWithMutLength! T, !_`中被定义
A type that represents a variable-length array. Use when the length is not known at compile time. There is a syntactic sugar called `[T]!`.
Defined by `Array! T = ArrayWithMutLength! T, !_`.

View file

@ -1,3 +1,3 @@
# Array T: Type
`Array T = ArrayWithLen T, _`定义。 有一种语法糖叫做`[T]`
Defined by `Array T = ArrayWithLen T, _`. There is a syntactic sugar called `[T]`.

View file

@ -1,34 +1,34 @@
# ArrayWithLen T: Type, N: Nat
`[T; N]`是语法糖。还有一个[`Array` 类型](./Array.md)省略了长度。
`[T; N]` is syntactic sugar. There is also an [`Array` type](./Array.md) that omits the length.
## methods
* values_at(self, selectors: [Nat; N]) -> [T; N]
```erg
``` erg
assert ["a", "b", "c", "d", "e"].values_at([0, 1, 3]) == ["a", "b", "d"]
```
* all(self, pred: T -> Bool) -> Bool
返回是否所有元素都满足 pred。
如果元素为 0则无论 pred 为 `True`,但会发出警告。
该规范本身已被多种语言采用,是逻辑一致性所必需的。
Returns whether all elements satisfy pred.
If the element is 0, it will be `True` regardless of pred, but a Warning will be issued.
This specification itself has been adopted by many languages and is required for logical consistency.
```erg
assert [].all(_ -> False)
```
``` erg
assert[].all(_ -> False)
```
```python
assert all(False for _ in [])
```
```python
assert all(False for _in[])
```
## methods of ArrayWithLen T, N | T <: Eq
* freq self -> [{T: Nat}]
返回对象出现的次数。
Returns the frequency of occurrence of an object.
```erg
``` erg
assert ["a", "b", "c", "b", "c", "b"].freq() \
== [{"a", 1}, {"b": 3}, {"c": 2}]
```
```

View file

@ -1,26 +1,34 @@
# ArrayWithMutLength! T: Type, N: Nat&excl;
# ArrayWithLen T: Type, N: Nat
一个可变长度数组,其长度在编译时已知。还有语法糖`ArrayWithMutLength(T, !N) == [T; !N]`
`[T; N]` is syntactic sugar. There is also an [`Array` type](./Array.md) that omits the length.
## methods
* push! ref! self(N ~> N+1, ...), elem: T
* values_at(self, selectors: [Nat; N]) -> [T; N]
* pop! ref! (N ~> N-1, ...) -> T
``` erg
assert ["a", "b", "c", "d", "e"].values_at([0, 1, 3]) == ["a", "b", "d"]
```
* sample!(ref! self) -> T
* sample! ref! self, M: Nat -> [T; M]
随机选择里面的一个元素并返回一个副本
* all(self, pred: T -> Bool) -> Bool
Returns whether all elements satisfy pred.
If the element is 0, it will be `True` regardless of pred, but a Warning will be issued.
This specification itself has been adopted by many languages and is required for logical consistency.
* shuffle!(ref! self)
把里面的东西随机摆放
``` erg
assert[].all(_ -> False)
```
* assert_len ref! self(_ ~> N, ...), N: Nat -> () or Panic
验证长度。
`panic!` 如果长度无效。
```python
assert all(False for _in[])
```
## Impl
## methods of ArrayWithLen T, N | T <: Eq
* From Range Int
* From [T; N]
* Num
* freq self -> [{T: Nat}]
Returns the frequency of occurrence of an object.
``` erg
assert ["a", "b", "c", "b", "c", "b"].freq() \
== [{"a", 1}, {"b": 3}, {"c": 2}]
```

View file

@ -1,6 +1,6 @@
# Complex
表示复数的类型。 在 Erg 中表示数字的类型,例如 Float、Int 和 Nat通常在顶部有这种类型
A type that represents a complex number. Types that represent numbers in Erg, such as Float, Int, and Nat, usually have this type at the top.
## supers
@ -11,4 +11,4 @@ Num and Norm
* abs
* conjugate
* imag
* real
* real

View file

@ -1,7 +1,7 @@
# Dict! K, V
表示字典哈希Map的类型。 有一个语法糖叫做`{K: V}`
A type that represents a dictionary (hashmap). There is a syntactic sugar called `{K: V}`.
## methods
* invert!(self) -> Self! V, K
* invert!(self) -> Self! V, K

View file

@ -1,6 +1,6 @@
# Either L, R = L or R
表示L或R的类型。 您可以将其视为Or类型的二元形式
A type that represents "either L or R". You can think of it as a two-limited form of the Or type.
## methods
@ -9,4 +9,4 @@
* andl
* andr
* mapl
* mapr
* mapr

View file

@ -1,8 +1,8 @@
# Float size
表示实数包含小数的数的类型。符合IEEE 754的浮点数在其他语言中一般是float的类型。
Float的大小为81byte~12816byte。如果只是Float则表示`Float64`
Erg 中的 0.1 实际上属于 Ratio 类型,而不是 Float 类型。没有浮点类型字面量,它是由 `(Ratio object)f64` 生成的(例如 (1/2)f64, 15f64。 f64 对应实数 1
A type that represents real numbers (numbers with decimals). Represents an IEEE 754 compliant floating-point number and is the general equivalent of float in other languages.
The size of Float size is 8(1byte)~128(16byte). A simple Float represents `Float 64`.
0.1 in Erg actually belongs to the Ratio type, not the Float type. There is no Float type literal, it is generated by `(Ratio object)f64` (e.g. (1/2)f64, 15f64). f64 corresponds to the real number 1.
## supers
@ -11,11 +11,11 @@ Complex and Ord
## methods
* sgn(self) -> {-1, 0, 1}
返回标志
returns the sign.
* truncate(self) -> Int
返回最接近自身的整数
Returns the integer closest to itself.
* separate(self) -> [Str]
* separate(self, dight: Nat) -> [Str]
按digit位数划分。没有自变量
* separate(self, date: Nat) -> [Str]
Separate by dight digits. 3 with no arguments.

View file

@ -4,6 +4,6 @@
* then(self, g: Self) -> Self
```erg
``` erg
assert f(g(x)) == f.then(g) x
```
```

View file

@ -1,7 +1,7 @@
# Inf
Inf是一个类其唯一实例是inf。
inf的主要用途是用于区间类型。
例如,大于等于 2 的整数类型是 `2..<inf`,小于等于 0 的实数是 `-inf<..0.0`
由于 inf 不是通常意义上的数字,所以不能按原样定义四个算术运算,
库中提供了所谓的扩展数字类例如ExtNat。
Inf is a class whose only instance is inf.
The main use of inf is with interval types.
For example, integer types greater than or equal to 2 are `2..<inf`, and real numbers less than or equal to 0 are `-inf<..0.0`.
Since inf is not a number in the usual sense, the four arithmetic operations cannot be defined as it is,
So-called extended number classes such as ExtNat are provided in the library.

View file

@ -1,10 +1,10 @@
# Int
表示整数的类。 实例为 0、1、-1、300000 等。
很多语言即使在表示自然数的时候也使用Int类型等价于但是Erg使用了使用更小的类型的原则
建议使用 Nat、NZInt、Interval 类型等。
Int是一种来自 Python 的类型,只有`Object`作为其超类型。
A class that represents an integer. Instances are 0, 1, -1, 300000, etc.
Many languages use Int (type equivalent to) even when representing natural numbers, but Erg uses the principle of use smaller types,
It is recommended to use Nat, NZInt, Interval type, etc.
Int is a type that comes from Python and has only `Object` as its supertype.
## supers
## methods
## methods

View file

@ -1,8 +1,8 @@
# IntRange L, R
`L..R`のクラス。
`L..R` class.
```erg
``` erg
IntRange L, R: Int == L..R
```
@ -10,10 +10,10 @@ IntRange L, R: Int == L..R
* .`_+_`: Self(L1, R1), Self(L2, R2) -> Self(L1+L2, R1+R2)
正常加法。 `Int``Nat` 的添加在此定义为假装它在每个类中定义
normal addition. Addition of `Int` and `Nat` is defined here under the pretense that it is defined in each class.
```erg
``` erg
0..10 + 1..12 == 1..22
Int + 0..10 == _..|Int|_ + 0..10 == _..|Int|_ == Int
Nat + Nat == 0.._ + 0.._ == 0.._ == Nat
```
```

View file

@ -1,18 +1,18 @@
# Interval begin, end := WellOrder
表示有序集合类型 (WellOrder) 的子类型的类型。Interval 类型具有派生类型,例如 PreOpen(x<..y)
A type that represents a subtype of the well-ordered set type (WellOrder). The Interval type has derived types such as PreOpen(x<..y).
```erg
``` erg
Months = 1..12
Alphabet = "a".."z"
Weekdays = Monday..Friday
Winter = November..December or January..February
```
```erg
0..1 # 整数范围
0.0..1.0 # 真实(有理)范围
# 或 0/1..1/1 相同
``` erg
0..1 # integer range
0.0..1.0 # real (rational) range
# or same for 0/1..1/1
```
计算机无法处理无限位数的数字,所以实数的范围实际上是有理数的范围。
Computers can't handle numbers with infinite digits, so the range of real numbers is actually the range of rational numbers.

View file

@ -1,7 +1,7 @@
# Matrix T: Num, Shape: [M, N]
表示矩阵的类型。 它继承自 Tensor[M, N]
A type that represents a matrix. It inherits from Tensor[M, N].
## def
Inherit Tensor T, [M, N]
Inherit Tensor T, [M, N]

View file

@ -1,10 +1,10 @@
# Nat
表示自然数的类型。 用于数组索引和范围类型
A type that represents a natural number. Used for array indices and range types.
## def
##def
```erg
``` erg
Nat = 0.._
```
@ -12,7 +12,7 @@ Nat = 0.._
* times!(self, p: () => NoneType) -> NoneType
```erg
``` erg
100.times! () =>
print! "hello!"
```
print! "hello!"
```

View file

@ -1,8 +1,8 @@
# Neg
表示负整数的类型。 Pos和Neg和{0} == Int
它还具有一些值得注意的属性,例如不被零除和 Neg * Neg == Pos
A type that represents a negative integer. Pos and Neg and {0} == Int.
It also has some notable properties such as no division by zero and Neg * Neg == Pos.
## def
##def
Inf<..-1
Inf<..-1

View file

@ -1,13 +1,13 @@
# Never
它是所有类型的子类型。 它是一个`Class`,因为它拥有所有的方法,当然还有 `.new`。但是它没有实例并且Erg会在即将创建的那一刻停止。
还有一种叫做`Panic`的类型没有实例,但是`Never`用于正常终止或故意无限循环,`Panic`用于异常终止。
It is a subtype of all types. It is a `Class` because it has all the methods and of course `.new`. However, it does not have an instance, and the Erg stops the moment it is about to be created.
There is also a type called `Panic` that does not have an instance, but `Never` is used for normal termination or an intentional infinite loop, and `Panic` is used for abnormal termination.
```erg
``` erg
# Never <: Panic
f(): Panic = exit 0 # OK
g(): Never = panic() # TypeError
```
`Never`/`Panic`的 OR 类型,例如`T 或 Never`可以转换为`T`。 这是因为`Never`在语义上是一个从不出现的选项(如果出现了,程序会立即停止)。
但是,在函数的返回值类型中使用时,`or Never`不能省略,因为它表示程序可能会终止。
The OR type of `Never`/`Panic`, eg `T or Never` can be converted to `T`. This is because `Never` is a semantically never-occurring option (if it does, the program stops immediately).
However, when using it in the return value type of a function, `or Never` cannot be omitted because it indicates that the program may terminate.

View file

@ -1,30 +1,30 @@
# NonZero N
# NonZeroN
表示非零数的类。 保证除零的安全性
A class that represents a non-zero number. The safety of division by zero is guaranteed.
```mermaid
classDiagram
class NonZero~Int~ {
...
}
class Int {
...
}
class Div {
<<trait>>
/(Self, R) -> O or Panic
}
class SafeDiv {
<<trait>>
/(Self, R) -> O
}
Int <|-- NonZero~Int~: Inherit
Div <|-- SafeDiv: Subsume
SafeDiv <|.. NonZero~Int~: Impl
Div <|.. Int: Impl
class Diagram
class NonZero~Int~ {
...
}
class Int {
...
}
class Div {
<<trait>>
/(Self, R) -> O or Panic
}
class SafeDiv {
<<trait>>
/(Self, R) -> O
}
Int <|-- NonZero~Int~: Inherit
Div <|-- SafeDiv: Subsume
SafeDiv <|..NonZero~Int~: Impl
Div <|.. Int: Impl
```
## methods
@Impl SafeDiv R, O
.`/`: Self.(R) -> O
.`/`: Self.(R) -> O

View file

@ -1,7 +1,7 @@
# Object
# Objects
它是所有类型的超类型
It is the supertype of all types.
## methods
* __sizeof__: Nat
* __sizeof__: Nat

View file

@ -1,7 +1,7 @@
# Operator [...T], O
是运算符的类型
is the type of the operator.
## def
##def
Inherit Func [...T], O
Inherit Func [...T], O

View file

@ -1,14 +1,14 @@
# Option T = T or NoneType
表示“可能失败”的类型。
A type that represents "may fail".
## methods
* unwrap(self, msg = "unwrapped a None value") -> T or Panic
提取它,期望内容是 `T` 类型。 如果是 `None`,则输出 `msg` 并恐慌
Extract it expecting the contents to be `T` type. If it is `None`, output `msg` and panic.
```erg
``` erg
x = "...".parse(Int).into(Option Int)
x.unwrap() # UnwrappingError: unwrapped a None value
x.unwrap("failed to convert from string to number") # UnwrappingError: failed to convert from string to number
@ -18,4 +18,4 @@ x.unwrap("failed to convert from string to number") # UnwrappingError: failed to
* unwrap_or_exec(self, f: () -> T) -> T
* unwrap_or_exec!(self, p!: () => T) -> T
* unwrap_or_exec!(self, p!: () => T) -> T

View file

@ -1,8 +1,8 @@
# Pos
Pos是一种表示正数大于或等于1的整数的类型。
由于不包括0因此具有消除被零除的可能性等优点。
Pos is a type that represents positive numbers (integers greater than or equal to 1).
Since 0 is not included, there are merits such as eliminating the possibility of division by zero.
## Def
`Pos = 1.._`
`Pos = 1.._`

View file

@ -1,5 +1,5 @@
# Ratio
#Ratio
表示有理数的类型。 它主要用于当您要使用分数时。
实际上Erg中的/运算符返回 Ratio。1/3等不被评估为 0.33333... 并且被处理为1/3。 此外0.1 相当于 1/10。 所以`0.1 + 0.2 == 0.3`。 这听起来很明显,但在 Python中它是False。
但是Ratio类型的效率往往比Float类型略低。 在执行速度很重要且不需要精确数值的地方应该使用浮点类型。 然而正如Rob Pike所说过早优化是万恶之源。 在丢弃Ratio类型并使用Float类型之前请进行真实的性能测试。 业余爱好者无条件偏爱较轻的模具。
A type that represents a rational number. It is mainly used when you want to use fractions.
In fact, the / operator in Erg returns Ratio. 1/3 etc. is not evaluated as 0.33333... and is processed as 1/3. Also, 0.1 is equivalent to 1/10. So `0.1 + 0.2 == 0.3`. It sounds obvious, but in Python it is False.
However, the Ratio type tends to be slightly less efficient than the Float type. Float type should be used at the point where execution speed is important and the exact numerical value is not required. However, as Rob Pike says, premature optimization is the root of all evil. Do a real performance test before discarding the Ratio type and using the Float type. Amateurs unconditionally prefer lighter molds.

View file

@ -1,14 +1,14 @@
# Record
记录所属的类。例如,`{i = 1}``Structural {i = Int}` 类型的元素,并且是`{i = Int}` 类的实例
请注意,其他类的实例是记录类型的元素,而不是记录类的实例
Class to which the record belongs. For example, `{i = 1}` is an element of type `Structural {i = Int}`, and is an instance of the `{i = Int}` class.
Note that instances of other classes are elements of the record type but not instances of the record class.
```erg
``` erg
assert not Structural({i = Int}) in Class
assert {i = Int} in Class
C = Class {i = Int}
c = C.new {i = 1}
c = C. new {i = 1}
assert c in Structural {i = Int}
assert not c in {i = Int}
```
```

View file

@ -1,7 +1,7 @@
# Result T, E
```erg
``` erg
Result T, E <: Error = Either T, E
```
`Option` 一样,它代表“一个可能失败的值”,但它可以有失败的上下文。 用法与`Either`几乎相同。
Like `Option`, it represents "a value that may fail", but it can have the context of failure. Usage is almost the same as `Either`.

View file

@ -1,3 +1,3 @@
# StrWithLen! N: Nat! = Inherit StrWithLen N
# StrWithLen!N: Nat! = Inherit StrWithLenN
表示可变长度字符串的类型
A type that represents a variable-length string.

View file

@ -1,9 +1,9 @@
# Str
(不变长度)表示字符串的类型。 简单的 `Str` 类型是删除了字符数的 `StrWithLen N` 类型(`Str = StrWithLen _`
(Invariant length) A type that represents a string. The simple `Str` type is the `StrWithLen N` type with the number of characters removed (`Str = StrWithLen _`).
## methods
* isnumeric
*isnumeric
返回字符串是否为阿拉伯数字。 使用 `isunicodenumeric` 判断汉字数字和其他表示数字的字符(注意此行为与 Python 不同)。
Returns whether the string is an Arabic numeral. Use `isunicodenumeric` to judge kanji numerals and other characters that represent numbers (note that this behavior is different from Python).

View file

@ -1,19 +1,19 @@
# Subroutine
# Subroutines
Func和Proc的基本类型。
Base type of Func and Proc.
## methods
* return
中断子程序并返回指定的值。 用于快速逃离嵌套
Interrupts a subroutine and returns the specified value. Useful for quickly escaping from a nest.
```erg
``` erg
f x =
for 0..10, i ->
if i == 5:
do
f::return i
do
log i
```
for 0..10, i ->
if i == 5:
do
f::return i
do
log i
```

View file

@ -1,16 +1,16 @@
# Tensor Shape: [Nat; N]
用于有效操作多维数组的类。 它还定义了诸如多维数组上的乘法之类的操作
Matrix、Vector 等都继承自该类型
A class for efficiently manipulating multidimensional arrays. It also defines operations such as multiplication on multidimensional arrays.
Matrix, Vector, etc. inherit from this type.
```erg
Tensor.arange(0..9) # Tensor [10]
``` erg
Tensor.arrange(0..9) #Tensor[10]
```
* reshape(self, NewShape: [Nat; M]) -> Self NewShape
```erg
(1..9).into(Tensor).reshape [3, 3]
``` erg
(1..9).into(Tensor).reshape[3, 3]
```
* identity i: Nat -> Self shape: [Nat; N]
@ -20,5 +20,5 @@ Tensor.arange(0..9) # Tensor [10]
* diag
* linspace
* logspace
* geomspace
*logspace
* geomspace

View file

@ -1,12 +1,12 @@
# TransCell! T: Type!
它是一个单元格,其内容可以针对每个模具进行更改。 由于它是T类型的子类型因此它也表现为T类型
当它在初始化时输入T时很有用并且在某个点之后总是输入U
It is a cell whose contents can be changed for each mold. Since it is a subtype of T type, it also behaves as T type.
It's useful when it's type T at initialization, and it's always type U after a certain point.
```erg
``` erg
a = TransCell!.new None
a: TransCell! !NoneType
a.set! 1
a: TransCell! !Int
assert a + 1 == 2
```
```

View file

@ -1,27 +1,27 @@
# Tuple T: ...Type
包含多种类型对象的集合
A collection that holds objects of multiple types.
## methods
* zip self, other
组合两个有序集合(数组或元组)
Composites two ordered collections (arrays or tuples).
```erg
assert ([1, 2, 3].zip [4, 5, 6])[0] == (1, 4)
```
``` erg
assert ([1, 2, 3].zip [4, 5, 6])[0] == (1, 4)
```
* zip_by self, op, other
一种泛化 zip 的方法。 您可以指定一个二进制操作来组合
`()``[]``{}``{:}` 也可以指定为运算符,分别生成元组、数组、集合和字典
```erg
assert ([1, 2, 3].zip([4, 5, 6]))[0] == (1, 4)
assert ([1, 2, 3].zip_by((), [4, 5, 6]))[0] == (1, 4)
assert ([1, 2, 3].zip_by([], [4, 5, 6]))[0] == [1, 4]
assert ([1, 2, 3].zip_by({}, [4, 5, 6]))[0] == {1, 4}
assert ([1, 2, 3].zip_by({:}, [4, 5, 6]))[0] == {1: 4}
assert ([1, 2, 3].zip_by(`_+_`, [4, 5, 6]))[0] == 5
```
A method that generalizes zip. You can specify a binary operation to compose.
`()`, `[]`, `{}`, `{:}` can also be specified as operators, and generate tuples, arrays, sets, and dicts respectively.
``` erg
assert ([1, 2, 3].zip([4, 5, 6]))[0] == (1, 4)
assert ([1, 2, 3].zip_by((), [4, 5, 6]))[0] == (1, 4)
assert ([1, 2, 3].zip_by([], [4, 5, 6]))[0] == [1, 4]
assert ([1, 2, 3].zip_by({}, [4, 5, 6]))[0] == {1, 4}
assert ([1, 2, 3].zip_by({:}, [4, 5, 6]))[0] == {1: 4}
assert ([1, 2, 3].zip_by(`_+_`, [4, 5, 6]))[0] == 5
```

View file

@ -1,3 +1,3 @@
# Vector T: Num, N: Nat
表示向量的类型。与同名的Rust和C++类型不同,这种类型只处理数字。
A type that represents a vector. Unlike Rust and C++ types with the same name, this type only handles numbers.

View file

@ -1,7 +1,7 @@
# BinOp L, R, O
二元运算符的类型
The type of the binary operator.
## Patches
Operator [L, R], O
Operator [L, R], O

View file

@ -1,7 +1,7 @@
# UnaryOp T, O
# Unary Op T, O
一元运算符的类型
The type of the unary operator.
## def
##def
Operator [T], O
Operator [T], O

View file

@ -1,34 +1,34 @@
# Add R
```erg
``` erg
Add R = Trait {
.AddO = Type
.`_+_` = (Self, R) -> Self.AddO
.AddO = Type
.`_+_` = (Self, R) -> Self.AddO
}
```
`Add`是一种定义加法的类型。加法有两种类型的`+`:方法和函数
`+`作为二元函数,即`_+_`,定义如下:
`Add` is a type that defines addition. There are two types of `+` as addition: methods and functions.
`+` as a binary function, i.e. `_+_`, is defined as follows.
```erg
``` erg
`_+_`(l: Add(R, O), r: R): O = l.`_+_` r
```
这个定义的目的是让 `+` 可以被视为一个函数而不是一个方法
The purpose of this definition is so that `+` can be treated as a function instead of a method.
```erg
``` erg
assert [1, 2, 3].fold(0, `_+_`) == 6
call op, x, y = op(x, y)
assert call(`_+_`, 1, 2) == 3
```
加法是这样输入的。
Addition is typed like this.
```erg
``` erg
f: |O: Type; A <: Add(Int, O)| A -> O
f x = x + 1
g: |A, O: Type; Int <: Add(A, O)| A -> O
g x = 1 + x
```
```

View file

@ -1,9 +1,9 @@
# Div R, O
如果除以零没有错误请使用“SafeDiv”
Use `SafeDiv` if there are no errors due to division by zero.
```erg
``` erg
Div R, O = Trait {
.`/` = Self.(R) -> O or Panic
.`/` = Self.(R) -> O or Panic
}
```
```

View file

@ -1,11 +1,11 @@
# Into T
一种类型表明它可以被类型转换为类型T。
即使Self和T之间没有继承关系也是在关系可以相互转换的时候定义的。
与继承不同,没有隐式转换。您必须始终调用 `.into` 方法。
A type that indicates that it can be type-converted to type T.
Even if there is no inheritance relationship between Self and T, it is defined when the relationship is convertible to each other.
Unlike inheritance, there is no implicit conversion. You must always call the `.into` method.
## methods
* into(self, T) -> T
変換を行います。
do the conversion.

View file

@ -2,7 +2,7 @@
## definition
```erg
``` erg
Num R = Add(R) and Sub(R) and Mul(R) and Eq
Num = Num Self
```
@ -13,4 +13,4 @@ Add and Sub and Mul and Eq
## methods
* `abs`
*`abs`

View file

@ -1,8 +1,8 @@
# SafeDiv R, O
```erg
``` erg
SafeDiv R, O = Subsume Div, {
@Override
.`/` = Self.(R) -> O
@Override
.`/` = Self.(R) -> O
}
```
```

View file

@ -1,31 +1,31 @@
# Sample
具有“随机”选择实例的`sample``sample!`方法的特征。`sample`方法总是返回相同的实例,而`sample!`方法返回一个随机实例,该实例随调用而变化
A trait that has a `sample` and `sample!` method that "randomly" picks an instance. The `sample` method always returns the same instance, and the `sample!` method returns a random instance that changes from call to call.
请注意,这是一个假设您想要一个适当的实例进行测试等的特征,并且它不一定是随机的。 如果您想要随机抽样,请使用“随机”模块。
Note that this is a trait that assumes that you want an appropriate instance for testing, etc., and that it is not necessarily random. If you want random sampling, use the `random` module.
所有主要的值类都实现了 `Sample`。它还在由“Sample”类组成的元组类型、记录类型、Or类型和筛选类型中实现
All major value classes implement `Sample`. It is also implemented in tuple types, record types, Or types, and sieve types that are composed of `Sample` classes.
```erg
assert Int.sample() == 42
assert Str.sample() == "example"
# Int默认在64bit范围内采样
print! Int.sample!() # 1313798
``` erg
assert Int. sample() == 42
assert Str. sample() == "example"
# Int is sampled in 64bit range by default
print! Int. sample!() # 1313798
print! {x = Int; y = Int}.sample!() # {x = -32432892, y = 78458576891}
```
下面是一个`Sample`的实现示例
Below is an implementation example of `Sample`.
```erg
``` erg
EmailAddress = Class {header = Str; domain = Str}, Impl=Sample and Show
@Impl Show
EmailAddress.
Email address.
show self = "{self::header}@{self::domain}"
@Impl Sample
EmailAddress.
Email address.
sample(): Self = Self.new "sample@gmail.com"
sample!(): Self =
domain = ["gmail.com", "icloud.com", "yahoo.com", "outlook.com", ...].sample!()
header = AsciiStr.sample!()
Self.new {header; domain}
```
header = AsciiStr. sample!()
Self. new {header; domain}
```

View file

@ -1,13 +1,13 @@
# Unpack
标记性状。实现时,元素可以像记录一样通过模式匹配来分解
marker trait. When implemented, elements can be decomposed by pattern matching like records.
```erg
C = Class {i = Int}, Impl=Unpack
``` erg
C = Class {i = Int}, Impl = Unpack
C.new i = Self::new {i;}
{i} = C.new(1)
D = Class C or Int
log match D.new(1):
(i: Int) -> i
({i}: C) -> i
```
(i: Int) -> i
({i}: C) -> i
```

View file

@ -5,7 +5,7 @@
* `Int and Str` => Multiple inheritance is not allowed, or `Int or Str`?
* `: [1, 2]` => `: {1, 2}`?
* `: [Int, 2]` => `: [Int; 2]`?
* `[Int; Str]` => `(Int, Str)` (Tuple) or `[Int: Str]` (Dict)?
* `[Int; Str]` => `(Int, Str)`(Tuple) or `[Int: Str]`(Dict)?
* `{x: Int}` => `{x = Int}`?
* `{x = Int}!` => `{x = Int!}`?
* `ref! immut_expr` => `ref!!immut_expr`?
* `ref! immut_expr` => `ref! !immut_expr`?

View file

@ -1,5 +1,5 @@
# warnings (not implemented yet)
* `t = {(record type)}` => `T = {(record type)}`? (only types defined as constants can be used for type specification)
* `{I: Int |...}!` => `{I: Int! |...}`
* `return x` ( `x!= ()`) in for/while block => `f::return` (outer block)?
* `{I: Int | ...}!` => `{I: Int! | ...}`
* `return x`(`x != ()`) in for/while block => `f::return` (outer block)?

View file

@ -1,10 +1,10 @@
# 废弃/拒绝的语言规范
# Abandoned/rejected language specifications
## 重载(临时多态性)
## Overloading (ad-hoc polymorphism)
被放弃了,因为它可以用参数+子类型多态来代替并且与Python的语义不兼容。 有关详细信息,请参阅 [overload](../syntax/type/overloading.md) 文章。
It was abandoned because it can be replaced by parametric + subtyping polymorphism, and it is incompatible with Python's semantics. See [overload](../syntax/type/overloading.md) article for details.
## 具有显式生命周期的所有权系统
## Ownership system with explicit lifetime
原计划引入 Rust 之类的所有权系统,但由于与 Python 的语义不兼容以及需要引入生命周期注解等复杂规范而被放弃,并且所有不可变对象都是 RC。托管的可变对象现在只有一个所有权.
Dyne 没有 C# 和 Nim 那样的 GIL策略是允许值对象和低级操作在安全范围内。
It was planned to introduce an ownership system like Rust, but it was abandoned due to its incompatibility with Python's semantics and the need to introduce complicated specifications such as lifetime annotations, and all immutable objects are RC. Managed, mutable objects now have only one ownership.
Dyne does not have a GIL like C# and Nim, and the policy is to allow value objects and low-level operations within a safe range.

View file

@ -36,4 +36,4 @@
## (6.(未来计划)转换字节码 -> LLVM IR)
* 字节码是基于堆栈的,而 LLVM IR 是基于寄存器的。
这个转换过程会多出几层中间过程。
这个转换过程会多出几层中间过程。

View file

@ -2,27 +2,27 @@
## AssignError
尝试重写不可变变量时发生
Raised when attempting to rewrite an immutable variable.
## AttributeError
尝试访问不存在的属性时发生
Raised when trying to access an attribute that does not exist.
## PurityError
当您在不允许副作用的范围内(函数、不可变类型等)编写导致副作用的代码时发生
Raised when writing code that causes side effects in scopes (functions, immutable types, etc.) where side effects are not allowed.
## MoveError
尝试访问已移动的变量时发生
Raised when you try to access a variable that has already been moved.
## BorrowError
在存在对对象的借用时尝试获取可变引用时发生
Raised when an attempt is made to obtain another variable reference while a borrow exists for an object.
## CyclicError
当你有一个明显不可阻挡的循环时发生
Raised when there is an apparent non-stop cycle.
```erg
i: Int = i
@ -38,58 +38,58 @@ U = T
## BytecodeError
当加载的字节码损坏时发生
Raised if the bytecode read is corrupt.
## CompileSystemError
在编译器内部发生错误时发生
Raised when an error occurs inside the compiler.
## EnvironmentError
如果您在安装期间没有访问权限,则会发生这种情况
Raised when there is no access permission during installation.
## FeatureError
在检测到未正式提供的实验性功能时发生
Raised when an experimental feature that is not officially provided is detected.
## ImportError
## IndentationError
检测到不良缩进时发生
派生自SyntaxError
Raised when an invalid indentation is detected.
Derived from SyntaxError.
## NameError
当您访问不存在的变量时发生
Raised when accessing a variable that does not exist.
## NotImplementedError
当您调用具有定义但没有实现的 API 时发生
派生自 TypeError
Raised when calling an API that has a definition but no implementation.
Derived from TypeError.
## PatternError
当检测到非法模式时发生
派生自SyntaxError
Raised when an invalid pattern is detected.
Derived from SyntaxError.
## SyntaxError
在检测到错误语法时发生
Raised when an invalid syntax is detected.
## TabError
在使用制表符进行缩进/间距时发生
派生自SyntaxError
Raised when a tab character is used for indentation/space.
Derived from SyntaxError.
## TypeError
当对象类型不匹配时发生
Raised when the object type does not match.
## UnboundLocalError
在定义之前使用变量时发生
更准确地说,它发生在以前使用过在范围内定义的变量时
Raised when a variable is used before it is defined.
More precisely, it occurs when a variable defined in a scope is used before it is defined.
```erg
i = 0
@ -99,8 +99,8 @@ f x =
y + i
```
在这段代码中,`y = i + x` 中的 `i` 是一个未定义的变量
但是,常量可以在定义之前在另一个函数中调用
In this code, the `i` in `y = i + x` is an undefined variable.
However, if it is a constant, it can be called in another function before it is defined.
```erg
f() = g()
@ -111,7 +111,7 @@ g() = f()
## SyntaxWarning
它在语法上很好,但是当我们检测到冗余或不常见的代码(不必要的 `()` 等)时就会发生这种情况
This happens when syntactically sound but redundant or uncommon code is detected (e.g., unnecessary `()`).
```erg
if (True): # SyntaxWarning: unnecessary parentheses
@ -120,12 +120,12 @@ if (True): # SyntaxWarning: unnecessary parentheses
## DeprecationWarning
在不推荐使用引用的对象时发生
(开发人员在生成此警告时应始终提供替代方法作为提示)
Raised if the referenced object is deprecated.
(Developers should always provide an alternative Hint when raising this Warning.)
## FutureWarning
当您检测到将来可能导致问题的代码时发生
此警告是由版本兼容性问题(包括库)以及语法和 API 的更改引起的
Raised when code is detected that may cause problems in the future.
This warning is caused by version compatibility issues (including libraries) or changes in syntax or API.
## ImportWarning

View file

@ -1,35 +1,35 @@
# 高レベル中間表現(HIR, High-level Intermediate Representation)
# High-level Intermediate Representation (HIR)
HIR 是 Erg 编译器从 AST 生成的结构
此结构包含源代码中每个表达式的完整类型信息,并且在语法上已脱糖
AST与源代码一一对应纯文本但是HIR去掉了不必要的代码信息添加了省略的类型信息所以HIR可以转换为源代码很难恢复
让我们在下面的代码中查看 HIR 的示例
A HIR is a struct that the Erg compiler generates from an AST.
This struct contains the complete type information for every expression in the source code and is desugared syntactically.
AST has a one-to-one correspondence with the source code (as plain text), but HIR has unnecessary code information removed and omitted type information added, so HIR can be converted to source code is difficult to restore.
Let's see an example of HIR in the code below.
```erg
``` erg
v = ![]
for! 0..10, i =>
v.push! i
v.push!i
log v.sum()
```
从此代码生成的 AST 如下所示:
The AST generated from this code looks like this:
```erg
``` erg
AST(Module[
VarDef{
sig: VarSignature{
sig: VarSignature {
pat: VarPattern::Ident(None, VarName("v")),
spec_t: None,
},
op: "=",
body: Block[
UnaryOp{
Unary Op {
op: "!",
expr: Array([]),
},
],
},
Call{
Call {
obj: Accessor::Local("for!"),
args: [
BinOp{
@ -38,16 +38,16 @@ AST(Module[
rhs: Literal(10),
},
Lambda{
sig: LambdaSignature{
sig: LambdaSignature {
params: [
ParamSignature{
Param Signature {
pat: ParamPattern::Name(VarName("i")),
},
],
spec_ret_t: None,
},
body: Block[
Call{
Call {
obj: Accessor::Attr{"v", "push!"},
args: [
Accessor::Local("i"),
@ -57,10 +57,10 @@ AST(Module[
},
],
},
Call{
Call {
obj: Accessor::Local("log"),
args: [
Call{
Call {
obj: Accessor::Attr("v", "sum"),
args: [],
}
@ -69,12 +69,12 @@ AST(Module[
])
```
从 AST 生成的 HIR 如下所示:
And the HIR generated from the AST looks like this:
```erg
``` erg
HIR(Module[
VarDef{
sig: VarSignature{
sig: VarSignature {
pat: VarPattern::Ident(None, Name("v")),
t: [0..10, _]!,
},
@ -87,7 +87,7 @@ HIR(Module[
},
],
},
Call{
Call {
obj: Accessor::Local{
name: "for!",
t: (Range Nat, Nat => NoneType) => NoneType,
@ -100,9 +100,9 @@ HIR(Module[
t: 0..10,
},
Lambda{
sig: LambdaSignature{
sig: LambdaSignature {
params: [
ParamSignature{
Param Signature {
pat: ParamPattern::Name(Name("i")),
t: 0..10,
},
@ -110,7 +110,7 @@ HIR(Module[
t: 0..10 => NoneType,
},
body: Block[
Call{
Call {
obj: Accessor::Attr{
obj: Accessor::Local("v"),
field: "push!",
@ -124,13 +124,13 @@ HIR(Module[
},
],
},
Call{
Call {
obj: Accessor::Local{
name: "log",
t: ...Object => NoneType,
},
args: [
Call{
Call {
obj: Accessor::Attr{
obj: Accessor::Local("v"),
field: "sum",
@ -144,5 +144,5 @@ HIR(Module[
])
```
对象类型被推断为尽可能小。 另一方面,子例程推断实现存在的类型
因此,实际参数的类型和形式参数的类型可能不匹配
Object types are inferred as small as possible. Subroutines, on the other hand, infer the type for which the implementation exists.
Therefore, the type of the actual argument and the type of the formal argument may not match.

View file

@ -1,62 +1,70 @@
# 类型推理算法
# type inference algorithm
> :本节正在编辑中,可能包含某些错误。
> __Warning__: This section is being edited and may contain some errors.
以下是使用的表示方法。
The notation used below is shown.
```erg
自由类型变量(类型,未绑定):?T, ?U,...
自由类型变量(值,未绑定):?a, ?b,...
输入环境 (Γ): { x: T,... }
类型分配规则 (S): { ?T --> T,...}
类型参数评估环境 (E): { e -> e',...}
``` erg
Free type variables (type, unbound): ?T, ?U, ...
Free-type variables (values, unbound): ?a, ?b, ...
type environment (Γ): { x: T, ... }
Type assignment rule (S): { ?T --> T, ... }
Type argument evaluation environment (E): { e -> e', ... }
```
下面的代码是一个示例。
Let's take the following code as an example.
```erg
``` erg
v = ![]
v.push! 1
print! v
```
Erg 类型推理的主要框架是 Hindley-Milner 类型推理算法(但进行了各种扩展)。具体来说,类型推论是按照以下步骤进行的。术语描述将在后面介绍。
Erg's type inference largely uses the Hindley-Milner type inference algorithm (although various extensions have been made). Specifically, type inference is performed by the following procedure. Terminology will be explained later.
1. 推断右边值的类型search
2. 使得到的类型具体化instantiate
3. 调用时进行类型赋值substitute
4. 体现单相特写resolve traits
5. 求值和简化类型变量值eval
6. 删除链接的类型变量deref
7. 对于可变依赖方法传播更改propagate
8. 如果左侧值存在且可调用则执行参数类型的一般化generalize
9. 如果有左侧值返回值类型一般化generalize
10. 如果赋值则在符号表中登记类型信息update
1. Infer the type of the rvalue (search)
2. instantiate the resulting type
3. If it is a call, perform type substitution (substitute)
4. Resolve traits that have already been monomorphized
5. Evaluate/reduce (eval) if there is a type variable value
6. Remove linked type variables (deref)
7. Propagate changes for mutable dependent methods
8. If there is an lvalue and it is Callable, generalize the argument type (generalize)
9. If there is an lvalue, generalize the (return value) type (generalize)
10. If it is an assignment, register the type information in the symbol table (`Context`) (update)
具体操作如下。
The specific operations are as follows.
line 1. Def{sig: v, block: ![]}
get block type:
get UnaryOp type:
get Array type: `['T; 0]`instantiate: `[?T; 0]`(substitute, eval are omitted)
update: `Γ: {v: [?T; 0]!}`expr returns `NoneType`: OK
getArray type: `['T; 0]`
instantiate: `[?T; 0]`
(substitute, eval are omitted)
update: `Γ: {v: [?T; 0]!}`
expr returns `NoneType`: OK
line 2. CallMethod{obj: v, name: push!, args: [1]}
line 2. CallMethod {obj: v, name: push!, args: [1]}
get obj type: `Array!(?T, 0)`
search: `Γ Array!(?T, 0).push!({1})`get: `= Array!('T ~> 'T, 'N ~> 'N+1).push!('T) => NoneType`instantiate: `Array!(?T, ?N).push!(?T) => NoneType`substitute(`S: {?T --> Nat, ?N --> 0}`): `Array!(Nat ~> Nat, 0 ~> 0+1).push!(Nat) => NoneType`eval: `Array!(Nat, 0 ~> 1).push!({1}) => NoneType`update: `Γ: {v: [Nat; 1]!}`
search: `Γ Array!(?T, 0).push!({1})`
get: `= Array!('T ~> 'T, 'N ~> 'N+1).push!('T) => NoneType`
instantiate: `Array!(?T, ?N).push!(?T) => NoneType`
substitute(`S: {?T --> Nat, ?N --> 0}`): `Array!(Nat ~> Nat, 0 ~> 0+1).push!(Nat) => NoneType`
eval: `Array!(Nat, 0 ~> 1).push!({1}) => NoneType`
update: `Γ: {v: [Nat; 1]!}`
expr returns `NoneType`: OK
line 3. Call{obj: print!, args: [v]}
get args type: `[[Nat; 1]!]`get obj type:
search: `Γ print!([Nat; 1]!)`get: `= print!(...Object) => NoneType`
line 3. Call {obj: print!, args: [v]}
get args type: `[[Nat; 1]!]`
get obj type:
search: `Γ print!([Nat; 1]!)`
get: `= print!(...Object) => NoneType`
expr returns `NoneType`: OK
## 实现类型变量
类型变量最初在的<gtr=43/>中表示如下。虽然现在以不同的形式实现,但本质上是相同的想法,所以我用更简单的表达方式——这个实现来思考。<gtr=44/><gtr=45/>的包装类型。
## Implementation of type variables
Type variables were originally expressed as follows in `Type` of [ty.rs](../../src/common/ty.rs). It's now implemented in a different way, but it's essentially the same idea, so I'll consider this implementation in a more naive way.
`RcCell<T>` is a wrapper type for `Rc<RefCell<T>>`.
```rust
pub enum Type {
@ -66,150 +74,158 @@ pub enum Type {
}
```
类型变量可以实现在外部字典中具有实体类型,而类型变量本身仅具有该键。然而,使用实现通常更有效(需要验证,<gtr=48/>)。
A type variable can be implemented by keeping the entity type in an external dictionary, and the type variable itself only has its keys. However, it is said that the implementation using `RcCell` is generally more efficient (verification required, [source](https://mobile.twitter.com/bd_gfngfn/status/1296719625086877696?s=21) ).
类型变量首先按进行初始化。此类型变量在代码分析过程中被重写,以确定类型。如果内容始终为 None则会产生一个类型变量不能立即确定为特定类型。例如<gtr=50/><gtr=51/>类型。我们将这种状态下的类型变量称为<gtr=52/>(确切术语未知)。与此相对,如果指定了某种特定类型,则称为<gtr=53/>
A type variable is first initialized as `Type::Var(RcCell::new(None))`.
This type variable is rewritten as the code is analyzed, and the type is determined.
If the content remains None until the end, it will be a type variable that cannot be determined to a concrete type (on the spot). For example, the type of `x` with `id x = x`.
I'll call a type variable in this state an __Unbound type variable__ (I don't know the exact terminology). On the other hand, we call a variable that has some concrete type assigned to it a __Linked type variable__.
这两种类型都是自由变量(很明显,我们认为这一术语是根据“自由变量”命名的)。这些是编译器用于推理的类型变量。这是因为它与程序员指定的类型变量不同,例如中的<gtr=55/>
Both are of the kind free type variables (the term is apparently named after "free variables"). These are type variables that the compiler uses for inference. It has such a special name because it is different from a type variable whose type is specified by the programmer, such as `'T` in `id: 'T -> 'T`.
未绑定变量应表示为和<gtr=57/>。在型理论的上下文中使用α和β的情况比较多,但是为了输入的简便化,采用了这个。请注意,这是一种用于一般讨论的符号,实际上并不是使用字符串标识符实现的。
Unbound type variables are expressed as `?T`, `?U`. In the context of type theory, α and β are often used, but this one is used to simplify input.
Note that this is a notation adopted for general discussion purposes and is not actually implemented using string identifiers.
当未绑定的变量被置于类型环境中时,它被替换为<gtr=59/>。这就是我们所说的<gtr=61/>。它类似于程序员指定的类型变量,如<gtr=60/>。它的内容只是一个字符串,不像自由变量那样可以链接到特定类型。
An unbound type variable `Type::Var` is replaced with a `Type::MonoQuantVar` when entering a type environment. This is called a __quantified type variable__. This is akin to the programmer-specified type variables, such as ``T``. The content is just a string, and there is no facility to link to a concrete type like a free-type variable.
将未绑定变量替换为量化变量的操作称为(或泛化)。如果仍然是未绑定的变量,则必须在一次调用中固定类型(例如,在<gtr=62/>调用后,<gtr=63/>的返回类型变为<gtr=64/>),因此必须将其一般化。这样,将在类型环境中注册包含量化变量的广义定义。
The operation of replacing unbound type variables with quantified type variables is called __generalization__ (or generalization). If you leave it as an unbound type variable, the type will be fixed with a single call (for example, after calling `id True`, the return type of `id 1` will be `Bool`), so It has to be generalized.
In this way a generalized definition containing quantified type variables is registered in the type environment.
## 一般化、类型方案、具体化
## generalizations, type schemes, reifications
将未绑定变量一般化的操作表示为<gtr=67/>。假设得到的广义变量为<gtr=68/>。在类型理论中,量化类型(例如,多相关数类型<gtr=69/>)通过在其前面加上<gtr=70/>来进行区分例如大块等符号称为全称量化器。这种表达式e.g.<gtr=71/>称为类型方案。Erg 中的类型方案表示为<gtr=72/>等。类型方案通常不被视为一级类型。这样配置类型系统可能会导致类型推理无法正常工作。然而在某些情况下Erg 被视为主要类型。有关详细信息,请参见<gtr=73/>
Let's denote the operation of generalizing an unbound type variable `?T` as `gen`. Let the resulting generalized type variable be `|T: Type| T`.
In type theory, quantified types, such as the polycorrelation type `α->α`, are distinguished by prefixing them with `∀α.` (symbols like ∀ are called (generic) quantifiers. ).
Such a representation (e.g. `∀α.α->α`) is called a type scheme. A type scheme in Erg is denoted as `|T: Type| T -> T`.
Type schemes are not usually considered first-class types. Configuring the type system that way can prevent type inference from working. However, in Erg, it can be regarded as a first-class type under certain conditions. See [rank2 type](../syntax/type/advanced/rank2type.md) for details.
现在当在类型推理中使用得到的类型方案e.g.必须取消一般化e.g.<gtr=75/><gtr=76/>)。这种反变换称为<gtr=78/>。我们将此操作称为<gtr=77/>
Now, when using the obtained type scheme (e.g. `'T -> 'T (id's type scheme)`) in type inference where it is used (e.g. `id 1`, `id True`), generalize must be released. This inverse transformation is called __instantiation__. We will call the operation `inst`.
```erg
``` erg
gen ?T = 'T
inst 'T = ?T (?T ∉ Γ)
```
重要的是,这两个操作都会替换该类型变量出现的所有位置。例如,如果将具体化,则得到<gtr=80/>。在实现过程中,需要 Dict 来替换它,但在一般化过程中,只需将<gtr=81/>链接到<gtr=82/>即可替换它。
Importantly, both operations replace all occurrences of the type variable. For example, if you instantiate `'T -> 'T`, you get `?T -> ?T`.
A replacement dict is required for instantiation, but for generalization, just link `?T` with `'T` to replace it.
然后给出参数的类型得到所需的类型。我们将此操作称为类型赋值Type substitution并将其表示为。此外<gtr=84/>表示当表达式是调用时获得返回类型的操作。第一个参数是参数类型列表,第二个参数是目标类型。
After that, give the type of the argument to get the target type. This operation is called type substitution, and will be denoted by `subst`.
In addition, the operation that obtains the return type if the expression is a call is denoted as `subst_call_ret`. The first argument is a list of argument types, the second argument is the type to assign to.
类型赋值规则表示将<gtr=86/><gtr=87/>重写为同一类型。此操作称为<gtr=91/><gtr=88/>也可以是类型变量。关于单一化的详细算法,请参见<gtr=90/>。单一化操作应表示为<gtr=89/>
The type substitution rule `{?T --> X}` means to rewrite `?T` and `X` to be of the same type. This operation is called __Unification__. `X` can also be a type variable.
A detailed unification algorithm is described in [separate section](./unification.md). We will denote the unify operation as `unify`.
```erg
``` erg
unify(?T, Int) == Ok(()) # ?T == (Int)
# Sは型代入規則、Tは適用する型
# S is the type assignment rule, T is the applicable type
subst(S: {?T --> X}, T: ?T -> ?T) == X -> X
# 型代入規則は{?T --> X, ?U --> T}
# Type assignment rules are {?T --> X, ?U --> T}
subst_call_ret([X, Y], (?T, ?U) -> ?U) == Y
```
## 半单一化
## semi-unification
单一化的一个亚种是半单一化__Semi-unification__。这是更新类型变量约束以满足子类型关系的操作。在某些情况下类型变量可以是单一变量也可以是不单一变量因此称为“半”单一变量。
A variant of unification is called semi-unification (__Semi-unification__). This is the operation that updates the type variable constraints to satisfy the subtype relation.
In some cases, type variables may or may not be unifying, hence the term "semi" unification.
例如,在赋值参数时会发生半单一化。实际参数类型必须是虚拟参数类型的子类型。如果参数的类型是类型变量,则必须更新子类型关系以满足该类型。
Semi-unification occurs, for example, during argument assignment.
because the type of the actual argument must be a subtype of the type of the formal argument.
If the argument type is a type variable, we need to update the subtype relation to satisfy it.
```erg
# 仮引数の型をTとすると
``` erg
# If the formal parameter type is T
f(x: T): T = ...
a: U
# U <: Tでなくてはならないさもなければ型エラー
# must be U <: T, otherwise type error
f(a)
```
## 一般化
## Generalization
一般化不是一项简单的工作。如果涉及多个范围,就需要对类型变量进行“级别管理”。为了了解等级管理的必要性,首先确认不引入等级管理的类型推理会产生问题。试着推论以下无名函数的类型。
Generalization is not a simple task. When multiple scopes are involved, "level management" of type variables becomes necessary.
In order to see the necessity of level management, we first confirm that type inference without level management causes problems.
Infer the type of the following anonymous function.
```erg
``` erg
x ->
y = x
y
```
首先Erg 分配类型变量如下所示。y 的类型也是未知的,但现阶段不指定它。
First, Erg allocates type variables as follows:
The type of y is also unknown, but is left unassigned for now.
```erg
``` erg
x(: ?T) ->
y = x
y
```
首先要确定的是右边值 x 的类型。右边的值是“使用”因此它是具体化的。但是x 的类型是一个自由变量,因此已经被具体化。因此,<gtr=93/>仍然是右边值的类型。
The first thing to determine is the type of the rvalue x. An rvalue is a "use", so we reify it.
But the type `?T` of x is already instantiated because it is a free variable. Yo`?T` becomes the type of the rvalue.
```erg
``` erg
x(: ?T) ->
y = x (: inst ?T)
y
```
在注册为类型 y 的左侧值时进行一般化。但是,稍后将会发现,这种一般化是不完整的,结果是错误的。
Generalize when registering as the type of lvalue y. However, as we will see later, this generalization is imperfect and produces erroneous results.
```erg
``` erg
x(: ?T) ->
y(: gen ?T) = x (: ?T)
y(:gen?T) = x(:?T)
y
```
```erg
``` erg
x(: ?T) ->
y(: 'T) = x
y
```
y 的类型现在是量化变量。在下一行中,<gtr=95/>被立即使用。具体化。
The type of y is now a quantified type variable `'T`. In the next line, `y` is used immediately. Concrete.
```erg
``` erg
x: ?T ->
y(: 'T) = x
y(: inst 'T)
```
需要注意的是,在实现过程中,必须生成与任何已存在的(自由)类型变量不同的(自由)类型变量(一般化也是如此)。这些类型变量称为新鲜类型变量。
Note that instantiation must create a (free) type variable that is different from any (free) type variables that already exist (generalization is similar). Such type variables are called fresh type variables.
```erg
``` erg
x: ?T ->
y = x
y(: ?U)
```
然后看得到的整个公式的类型。。但很明显,这个公式应该是,你会发现推理有问题。之所以会这样,是因为我们没有对类型变量进行“级别管理”。
And look at the type of the resulting whole expression. `?T -> ?U`.
But obviously this expression should be `?T -> ?T`, so we know there is a problem with the reasoning.
This happened because we didn't "level manage" the type variables.
因此,使用以下符号引入类型变量的级别。级别以自然数表示。
So we introduce the level of type variables with the following notation. Levels are expressed as natural numbers.
```erg
# 通常のType型変数
``` erg
# normal type variable
?T<1>, ?T<2>, ...
# 部分型制約を付けられた型変数
?T<1>(<: U) or ?T(<: U)<1>, ...
# type variable with subtype constraint
?T<1>(<:U) or ?T(<:U)<1>, ...
```
现在,我再试一次。
Let's try again.
```erg
``` erg
x ->
y = x
y
```
首先,按如下所示赋值级别变量。顶级级别为 1. 范围越深,等级就越高。函数的参数属于内部范围,因此它位于比函数本身大一个级别。
First, assign a leveled type variable as follows: The toplevel level is 1. As the scope gets deeper, the level increases.
Function arguments belong to an inner scope, so they are one level higher than the function itself.
```erg
``` erg
# level 1
x (: ?T<2>) ->
# level 2
@ -217,85 +233,82 @@ x (: ?T<2>) ->
y
```
首先,将右边值具体化。和刚才一样,什么都不会改变。
First, instantiate the rvalue `x`. Same as before, nothing changed.
```erg
``` erg
x (: ?T<2>) ->
y = x (: inst ?T<2>)
y
```
从这里开始就是基莫。这是分配给类型左边值时的一般化。刚才这里的结果很奇怪,所以我们要改变广义算法。如果类型变量的级别小于或等于当前范围的级别,则一般化后将保持不变。
Here is the key. This is a generalization when assigning to the type of lvalue `y`.
Earlier, the results were strange here, so we will change the generalization algorithm.
If the level of the type variable is less than or equal to the level of the current scope, generalization leaves it unchanged.
```erg
``` erg
gen ?T<n> = if n <= current_level, then= ?T<n>, else= 'T
```
```erg
``` erg
x (: ?T<2>) ->
# current_level = 2
y (: gen ?T<2>) = x (: ?T<2>)
y(: gen ?T<2>) = x(: ?T<2>)
y
```
也就是说,左边值的类型为<gtr=101/>
That is, the lvalue `y` has type `?T<2>`.
```erg
``` erg
x (: ?T<2>) ->
# ↓ not generalized
y (: ?T<2>) = x
# ↓ not generalized
y(: ?T<2>) = x
y
```
y 的类型现在为未绑定变量。在下一行中进行说明。但是,<gtr=103/>类型并不通用,因此不会发生任何情况。
The type of y is now an unbound type variable `?T<2>`. Concrete with the following lines: but the type of `y` is not generalized, so nothing happens.
```erg
``` erg
x (: ?T<2>) ->
y (: ?T<2>) = x
y(: ?T<2>) = x
y (: inst ?T<2>)
```
```erg
``` erg
x (: ?T<2>) ->
y = x
y (: ?T<2>)
```
成功地得到了正确的类型。
We successfully got the correct type `?T<2> -> ?T<2>`.
我再看一个例子。这是更常见的情况,函数,运算符应用,前向参照。
Let's see another example. This is the more general case, with function/operator application and forward references.
```erg
f x, y = id(x) + y
``` erg
fx, y = id(x) + y
id x = x
f 10, 1
f10,1
```
让我们一条一条地看。
Let's go through it line by line.
在推论中,引用了后面定义的函数常量<gtr=106/>。在这种情况下,可以在<gtr=107/>之前插入一个声明<gtr=108/>,并分配一个自由变量。请注意,此时类型变量的级别为。这是为了避免在其他函数中被一般化。
During the inference of `f`, the later defined function constant `id` is referenced.
In such a case, insert a hypothetical declaration of `id` before `f` and assign a free-type variable to it.
Note that the level of the type variable at this time is `current_level`. This is to avoid generalization within other functions.
```erg
``` erg
id: ?T<1> -> ?U<1>
f x (: ?V<2>), y (: ?W<2>) =
id(x) (: subst_call_ret([inst ?V<2>], inst ?T<1> -> ?U<1>)) + y
```
类型变量之间的统一会将较高级别的类型变量替换为较低级别的类型变量。如果级别相同,这两个级别都可以。
Unification between type variables replaces higher-level type variables with lower-level type variables.
It doesn't matter which one if the level is the same.
类型变量之间的半单一化,情况稍有不同。对于不同级别的类型变量,不能相互施加类型约束。
Semiunification between type variables is a little different.
Type variables at different levels must not impose type constraints on each other.
```erg
``` erg
# BAD
f x (: ?V<2>), y (: ?W<2>) =
# ?V<2>(<: ?T<1>)
@ -303,71 +316,64 @@ f x (: ?V<2>), y (: ?W<2>) =
id(x) (: ?U<1>) + y (: ?W<2>)
```
这样,你就无法确定类型变量的具体体现位置。对于 Type 类型变量,请执行常规的单一化,而不是半单一化。也就是说,让他们单一化到低级别。
This makes it impossible to determine where to instantiate the type variable.
For Type type variables, normal unification is performed instead of semi-unification.
In other words, unify to the lower level.
```erg
``` erg
# OK
f x (: ?V<2>), y (: ?W<2>) =
# ?V<2> --> ?T<1>
id(x) (: ?U<1>) + y (: ?W<2>)
```
```erg
``` erg
f x (: ?T<1>), y (: ?W<2>) =
(id(x) + x): subst_call_ret([inst ?U<1>, inst ?W<2>], inst |'L <: Add('R)| ('L, 'R) -> 'L.AddO)
(id(x) + x): subst_call_ret([inst ?U<1>, inst ?W<2>], inst |'L <: Add('R)| ('L, 'R) -> 'L .AddO)
```
```erg
``` erg
f x (: ?T<1>), y (: ?W<2>) =
(id(x) + x): subst_call_ret([inst ?U<1>, inst ?W<2>], (?L(<: Add(?R<2>))<2>, ?R<2>) -> ?L<2>.AddO)
(id(x) + x): subst_call_ret([inst ?U<1>, inst ?W<2>], (?L(<: Add(?R<2>))<2>, ?R<2 >) -> ?L<2>.AddO)
```
```erg
``` erg
id: ?T<1> -> ?U<1>
f x (: ?T<1>), y (: ?W<2>) =
# ?U<1>(<: Add(?W<2>)) # 继承 ?L 的约束
# ?U<1>(<: Add(?W<2>)) # Inherit the constraints of ?L
# ?L<2> --> ?U<1>
# ?R<2> --> ?W<2> (?R(:> ?W), ?W(<: ?R)とはしない)
# ?R<2> --> ?W<2> (not ?R(:> ?W), ?W(<: ?R))
(id(x) + x) (: ?U<1>.AddO)
```
```erg
``` erg
# current_level = 1
f(x, y) (: gen ?T<1>, gen ?W<2> -> gen ?U<1>.AddO) =
id(x) + x
```
```erg
``` erg
id: ?T<1> -> ?U<1>
f(x, y) (: |'W: Type| (?T<1>, 'W) -> gen ?U<1>(<: Add(?W<2>)).AddO) =
id(x) + x
```
```erg
``` erg
f(x, y) (: |'W: Type| (?T<1>, 'W) -> ?U<1>(<: Add(?W<2>)).AddO) =
id(x) + x
```
在定义时进行升级以使其一般化。
When defining, raise the level so that it can be generalized.
```erg
``` erg
# ?T<1 -> 2>
# ?U<1 -> 2>
id x (: ?T<2>) -> ?U<2> = x (: inst ?T<2>)
```
如果已分配返回类型,则将返回类型与返回类型合并()。
If the return type has already been assigned, unify with the resulting type (`?U<2> --> ?T<2>`).
```erg
``` erg
# ?U<2> --> ?T<2>
f(x, y) (: |'W: Type| (?T<2>, 'W) -> ?T<2>(<: Add(?W<2>)).AddO) =
id(x) + x
@ -375,62 +381,58 @@ f(x, y) (: |'W: Type| (?T<2>, 'W) -> ?T<2>(<: Add(?W<2>)).AddO) =
id(x) (: gen ?T<2> -> gen ?T<2>) = x (: ?T<2>)
```
如果一个类型变量只是一个类型变量,则它所依赖的类型变量也是一个类型变量。一般化类型变量在每个函数中都是独立的。
If the type variable has been instantiated into a simple Type variable,
The type variable that depends on it will also be a Type type variable.
Generalized type variables are independent for each function.
```erg
``` erg
f(x, y) (: |'W: Type, 'T <: Add('W)| ('T, 'W) -> 'T.AddO) =
id(x) + x
id(x) (: |'T: Type| 'T -> gen 'T) = x
```
```erg
``` erg
f x, y (: |'W: Type, 'T <: Add('W)| ('T, 'W) -> 'T.AddO) =
id(x) + y
id(x) (: 'T -> 'T) = x
f(10, 1) (: subst_call_ret([inst {10}, inst {1}], inst |'W: Type, 'T <: Add('W)| ('T, 'W) -> 'T.AddO)
f(10, 1) (: subst_call_ret([inst {10}, inst {1}], inst |'W: Type, 'T <: Add('W)| ('T, 'W) -> 'T .AddO)
```
```erg
f(10, 1) (: subst_call_ret([inst {10}, inst {1}], (?T<1>(<: Add(?W<1>)), ?W<1>) -> ?T<1>.AddO))
``` erg
f(10, 1) (: subst_call_ret([inst {10}, inst {1}], (?T<1>(<: Add(?W<1>)), ?W<1>) -> ? T<1>.AddO))
```
类型变量将扩展到其实现的最小类型。
Type variables are bounded to the smallest type that has an implementation.
```erg
``` erg
# ?T(:> {10} <: Add(?W<1>))<1>
# ?W(:> {1})<1>
# ?W(:> {1})<1> <: ?T<1> (:> {10}, <: Add(?W(:> {1})<1>))
# 序列化
# serialize
# {1} <: ?W<1> or {10} <: ?T<1> <: Add({1}) <: Add(?W<1>)
# Add(?W)(:> ?V) 的最小实现特征是 Add(Nat) == Nat因为 Add 相对于第一个参数是协变的
# The minimal implementation trait for Add(?W)(:> ?V) is Add(Nat) == Nat, since Add is covariant with respect to the first argument
# {10} <: ?W<1> or {1} <: ?T<1> <: Add(?W<1>) <: Add(Nat) == Nat
# ?T(:> ?W(:> {10}) or {1}, <: Nat).AddO == Nat # 如果只有一个候选人则固定评分
# ?T(:> ?W(:> {10}) or {1}, <: Nat).AddO == Nat # If there is only one candidate, finalize the evaluation
f(10, 1) (: (?W(:> {10}, <: Nat), ?W(:> {1})) -> Nat)
# 程序到此结束,所以去掉类型变量
# This is the end of the program, so remove the type variable
f(10, 1) (: ({10}, {1}) -> Nat)
```
因此,整个程序的类型是这样的。
The resulting type for the entire program is:
```erg
``` erg
f|W: Type, T <: Add(W)|(x: T, y: W): T.AddO = id(x) + y
id|T: Type|(x: T): T = x
f(10, 1): Nat
```
重新提示原始未显式输入的程序。
I've also reprinted the original, unexplicitly typed program.
```erg
f x, y = id(x) + y
``` erg
fx, y = id(x) + y
id x = x
f(10, 1)
```
```

View file

@ -1,36 +1,36 @@
# 概览
# overview of `erg`
介绍每个图层的工作方式以及特别重要的函数和方法。
We will introduce the function of each layer and the particularly important functions and methods.
## 1. 词法分析
## 1. Lexical Analysis
* 执行词法分析。(<gtr=4/>作为迭代器实现)是词法分析的主要逻辑。将输出<gtr=5/>作为分析的结果。
* The `Lexer` does the lexical analysis. `Lexer::next` (`Lexer` is implemented as an iterator) is responsible for the main logic of lexical analysis. `Token` is output as a result of parsing.
## 2. 语法分析
## 2. Parsing
* 执行解析。尤其重要的是。作为分析的结果,将输出<gtr=9/>,它是<gtr=8/>的集合。
* `Parser` does the parsing. Of particular importance is `Parser::parse_expr`. As a result of parsing, `AST` which is a collection of `ast::Expr` is output.
## 3. 脱糖
## 3. Desugaring
* 进行脱糖。将输出。
* Desugaring is done by `Desugarer`. `AST` will be output.
## 4. 类型检查/类型推理
## 4. Type checking/type inference
* 用于输入数据。类型检查主要通过进行。特别重要的是<gtr=14/>(确定子类型关系),<gtr=15/>(对类型变量进行单一化/半单一化)和<gtr=16/>(定义嵌入式 API。将输出<gtr=17/>作为分析的结果。
* `ASTLowerer` does the typing. Type checking is primarily done by the `Context`. Especially important are `Context::supertype_of` (determine subtype relation), `Context::unify/sub_unify` (unify/semi-unify type variables), `Context::init_builtin_*`( defines built-in APIs). `HIR` is output as a result of analysis.
## 5. 副作用检查
## 5. Side effect check
*
* `SideEffectChecker` does.
## 6. 所有权检查
## 6. Ownership check
*
* `OwnershipChecker` does.
## 7. 字节码生成
## 7. Bytecode Generation
* <gtr=21/>转换为<gtr=22/><gtr=23/>保留字节码和执行设置。尤其重要的是。
* `CodeGenerator` converts `HIR` to `CodeObj`. `CodeObj` holds bytecode and execution configuration. Of particular importance is `CodeGenerator::compile_expr`.
---
* 所有这些操作都由作为外立面进行总结。
* 生成的字节码当然由 Python 执行,但它被称为。
* All the above processing is put together by the `Compiler` as a facade.
* Of course Python executes the generated bytecode, which is called `DummyVM`.

View file

@ -1,9 +1,9 @@
# 解析 Erg 语言
# Parsing the Erg language
## 处理空白
在 Erg 的语法中,特别的是 space-sensitive根据空白进行区分这一点。这是为了弥补的省略导致的表现力下降。同样的语法也可以在可以省略<gtr=4/>的 Nim 中看到。
## Treatment of whitespace
A peculiarity of Erg's grammar is that it is space-sensitive.
This is to compensate for the loss of expressiveness caused by the omission of `()`. A similar syntax is found in Nim, which also allows the omission of `()`.
```erg
f +1 == f(+1)
@ -14,18 +14,20 @@ f(1,) == f(1)
(f() -> ...) == (f() -> ...)
```
## 左侧值,右侧值
在 Erg 中,所谓左边值并不是的左侧这样简单的值。实际上,<gtr=6/>的左侧也存在右边值(非常容易混淆),<gtr=7/>的右侧也存在左边值。甚至在右边值中存在左边值。
## Left-hand side value, right-hand side value
In Erg, left-hand side values are not as simple as the left-hand side of `=`.
In fact, there is (very confusingly) a right-sided value on the left side of `=`, and a left-sided value on the right side of `=`.
There can even be a left-side value within a right-side value.
```erg
# iは左辺値、Array(Int)と[1, 2, 3]は右辺値
# i is the left-hand side value, Array(Int) and [1, 2, 3] are the right-hand side values
i: Array(Int) = [1, 2, 3]
# `[1, 2, 3].iter().map i -> i + 1`は右辺値だが、->の左側のiは左辺値
# `[1, 2, 3].iter().map i -> i + 1` is the right-hand side value, but i to the left of -> is the left-hand side value
a = [1, 2, 3].iter().map i -> i + 1
# {x = 1; y = 2}は右辺値だが、x, yは左辺値
# {x = 1; y = 2} is the right side value, but x, y are the left side values
r = {x = 1; y = 2}
```
左边值、右边值的正确定义是“如果可以评价的话是右边值,如果不是的话是左边值”。以这一代码为例。第 2 个<gtr=9/>是可以评价的右边值,第 1 个<gtr=10/>是左边值。
The precise definition of left- and right-hand side values is "right-hand side value if it is evaluable, otherwise left-hand side value".
As an example, consider the code ``i = 1; i``, where the second `i` is a right-sided value because it is evaluable, but the first `i` is a left-sided value.

View file

@ -1,19 +1,18 @@
# 筛子型
# Sieve type
筛型是指以下类型。
The sieve type is the following type.
```erg
``` erg
{I: Int | I >= 0}
{S: StrWithLen N | N >= 1}
{T: (Ratio, Ratio) | T.0 >= 0; T.1 >= 0}
```
在 Erg 中,通过将 EnumInterval 型转换为筛子型,可以进行型的判定。
Erg enables type determination by converting Enum and Interval types into sieve types.
## 转换为筛子类型
## Convert to sieve type
在 [筛型] 一项中,区间型和列举型是筛型的糖衣句法。分别进行如下变换。
In the section [Sieve types], we said that interval types and enum types are syntactic sugar for sieve types. Each is converted as follows.
* {0} -> {I: Int | I == 0}
* {0, 1} -> {I: Int | I == 0 or I == 1}
@ -24,37 +23,36 @@
* {0} and {-3, 0} -> {I: Int | I == 0 and (I == -3 or I == 0)}
* {0} not {-3, 0} or 1.._ -> {I: Int | I == 0 and not (I == -3 or I == 0) or I >= 1}
## 筛子型的类型判定
说明判断筛子 A 是否是另一筛子 B 的亚型的算法。在形式上,(所有)子类型确定定义如下。
## Sieve type detection
An algorithm for determining whether a sieve type A is a subtype of another sieve type B is described. Formally, (all) subtyping is defined as follows:
```console
A <: B <=> ∀a∈A; a ∈ B
```
具体应用以下推论规则。布尔式简化完毕。
Specifically, the following inference rules are applied. Boolean expressions are assumed to be simplified.
* 区间化规则(根据类型定义自动执行)
* intervalization rules (done automatically from type definition)
* `Nat` => `{I: Int | I >= 0}`
* 切上规则
* Round-up rule
* `{I: Int | I < n}` => `{I: Int | I <= n-1}`
* `{I: Int | I > n}` => `{I: Int | I >= n+1}`
* `{R: Ratio | R < n}` => `{R: Ratio | R <= n-ε}`
* `{R: Ratio | R > n}` => `{R: Ratio | R >= n+ ε}`
* 反转规则
* `{R: Ratio | R > n}` => `{R: Ratio | R >= n+ε}`
* reversal rule
* `{A not B}` => `{A and (not B)}`
* 德-摩根定律
* De Morgan's Law
* `{not (A or B)}` => `{not A and not B}`
* `{not (A and B)}` => `{not A or not B}`
* 分配规则
* `{A and (B or C)} <: D` => `{(A and B) or (A and C)} <: D` => `({A and B} <: D) and ({A and C} <: D)`
* `{(A or B) and C} <: D` => `{(C and A) or (C and B)} <: D` => `({C and A} <: D) and ({C and B} <: D)`
* `D <: {A or (B and C)}` => `D <: {(A or B) and (A or C)}` => `(D <: {A or B}) and (D <: {A or C})`
* `D <: {(A and B) or C}` => `D <: {(C or A) and (C or B)}` => `(D <: {C or A}) and (D <: {C or B})`
* Distribution rule
* `{A and (B or C)} <: D` => `{(A and B) or (A and C)} <: D` => `({A and B} <: D) and ( {A and C} <: D)`
* `{(A or B) and C} <: D` => `{(C and A) or (C and B)} <: D` => `({C and A} <: D) and ( {C and B} <: D)`
* `D <: {A or (B and C)}` => `D <: {(A or B) and (A or C)}` => `(D <: {A or B}) and ( D <: {A or C})`
* `D <: {(A and B) or C}` => `D <: {(C or A) and (C or B)}` => `(D <: {C or A}) and ( D <: {C or B})`
* `{A or B} <: C` => `({A} <: C) and ({B} <: C)`
* `A <: {B and C}` => `(A <: {B}) and (A <: {C})`
* 终止规则
* termination rule
* {I: T | ...} <: T = True
* {} <: _ = True
* _ <: {...} = True
@ -64,42 +62,41 @@ A <: B <=> ∀a∈A; a ∈ B
* {I >= a and I <= b} (a < b) <: {I <= d} = (b <= d)
* {I >= a} <: {I >= c or I <= d} (c >= d) = (a >= c)
* {I <= b} <: {I >= c or I <= d} (c >= d) = (b <= d)
* {I >= a and I <= b} (a <= b) <: {I >= c or I <= d} (c > d) = ((a >= c) or (b <= d))
* 基本公式
* {I >= a and I <= b} (a <= b) <: {I >= c or I <= d} (c > d) = ((a >= c) or (b <= d ))
* basic formula
* {I >= l} <: {I >= r} = (l >= r)
* {I <= l} <: {I <= r} = (l <= r)
* {I >= l} <: {I <= r} = False
* {I <= l} <: {I >= r} = False
布尔式的简化规则如下。minmax 可能无法移除。此外,多个排列的 orand 被转换为嵌套的 minmax。
The simplification rules for Boolean expressions are as follows. min, max may not be removed. Also, multiple or, and are converted to nested min, max.
* 排序规则
* ordering rules
* `I == a` => `I >= a and I <= a`
* `i!= a` => `I >= a+1 or I <= a-1`
* 恒真规则
* `i != a` => `I >= a+1 or I <= a-1`
* Consistency rule
* `I >= a or I <= b (a < b)` == `{...}`
* 恒伪规则
* Constancy rule
* `I >= a and I <= b (a > b)` == `{}`
* 更换规则
* 顺序表达式按,<gtr=62/>的顺序进行替换。
* 延长规则
* replacement rule
* Replace order expressions in the order `I >= n` and `I <= n`.
* Extension rule
* `I == n or I >= n+1` => `I >= n`
* `I == n or I <= n-1` => `I <= n`
* 最大规则
* maximum rule
* `I <= m or I <= n` => `I <= max(m, n)`
* `I >= m and I >= n` => `I >= max(m, n)`
* 最小规则
* minimum rule
* `I >= m or I >= n` => `I >= min(m, n)`
* `I <= m and I <= n` => `I <= min(m, n)`
* 删除规则
* 左边的,在右边有<gtr=76/><gtr=77/><gtr=78/>时可以去除。
* 如果不能移除左边的所有等式,则返回 False
* elimination rule
* `I == n` on the left side is removed when `I >= a (n >= a)` or `I <= b (n <= b)` or `I == n` on the right side can.
* False if all left-hand equations cannot be eliminated
e.g.
```python
1.._ <: Nat
1.._<: Nat
=> {I: Int | I >= 1} <: {I: Int | I >= 0}
=> {I >= 1} <: {I >= 0}
=> (I >= 0 => I >= 1)
@ -109,7 +106,6 @@ e.g.
# {I <= l} <: {I <= r} == (l <= r)
```
```python
{I: Int | I >= 0} <: {I: Int | I >= 1 or I <= -3}
=> {I >= 0} <: {I >= 1 or I <= -3}
@ -118,7 +114,6 @@ e.g.
=> False
```
```python
{I: Int | I >= 0} <: {I: Int | I >= -3 and I <= 1}
=> {I >= 0} <: {I >= -3 and I <= 1}
@ -127,29 +122,28 @@ e.g.
=> False
```
```python
{I: Int | I >= 2 or I == -2 or I <= -4} <: {I: Int | I >= 1 or I <= -1}
=> {I >= 2 or I <= -4 or I == -2} <: {I >= 1 or I <= -1}
=> {I >= 2 or I <= -4} <: {I >= 1 or I <= -1}
=> {I >= 2 or I <= -4} <: {I >= 1 or I <= -1}
and {I == -2} <: {I >= 1 or I <= -1}
=> {I >= 2} <: {I >= 1 or I <= -1}
=> {I >= 2} <: {I >= 1 or I <= -1}
and {I <= -4} <: {I >= 1 or I <= -1}
and
{I == -2} <: {I >= 1}
or {I == -2} <: {I <= -1}
=> {I >= 2} <: {I >= 1}
=> {I >= 2} <: {I >= 1}
or {I >= 2} <: {I <= -1}
and
{I <= -4} <: {I >= 1}
or {I <= -4} <: {I <= -1}
and
False or True
=> True or False
=> True or False
and
False or True
and
True
=> True and True
=> True
```
```

View file

@ -1,27 +1,33 @@
# 解决修补程序方法
# Resolving patch methods
是大于 0 的<gtr=9/>,即<gtr=10/>的子类型。本来不存在于 Python 的类阶层中。Erg 如何解决这个补丁的方法呢?
`Nat` is zero or more `Int`, a subtype of `Int`.
`Nat` does not exist in the Python class hierarchy. I wonder how Erg solves this patch method?
```erg
``` erg
1.times do:
log "hello, world"
log "hello world"
```
<gtr=13/>的补丁方法。由于<gtr=14/><gtr=15/>的实例,所以首先要沿着<gtr=16/>的 MRO方法解析顺序进行搜索。Erg 在<gtr=17/>的 MRO 中有<gtr=18/><gtr=19/>。它来自 Python在 Python 中<gtr=20/>)。<gtr=21/>方法在这两个方法中都不存在。从这里开始,进入该子类型的探索。
`.times` is a `NatImpl` patch method.
Since `1` is an instance of `Int`, it is first searched by tracing the MRO (Method Resolution Order) of `Int`.
Erg has `Int`, `Object` in the MRO of `Int`. It comes from Python (`int.__mro__ == [int, object]` in Python).
The `.times` method does not exist in either of them. Now let's explore that subtype.
~
整数在其上位型中显然应该具有实数和复数,甚至是整体数,但在与 Python 具有互换性的层中却不出现这一事实。但是实际上在 Erg 中,和<gtr=23/><gtr=24/>。至于<gtr=25/>,虽然是与<gtr=26/>没有继承关系的类,但作为类型被判断为具有互换性。究竟是怎么回事?
Integers should obviously have reals, complexes, and even whole numbers in their supertypes, but that fact does not appear in the Python-compatible layer.
However, `1 in Complex` and `1 in Num` are actually `True` in Erg.
As for `Complex`, even though it is a class that does not have an inheritance relationship with `Int`, it is judged to be compatible as a type. What the hell is going on?
~
对于某个对象,其所属的类型有无数个。但是实际上必须考虑的是拥有方法的类型,即只有拥有名字的类型。
An object has an infinite number of types to which it belongs.
But we really only have to think about types with methods, i.e. types with names.
Erg 编译器拥有所有提供方法及其安装的补丁型散列映射。每次新定义类型时,此表都会更新。
The Erg compiler has a hashmap of patch types with all provided methods and their implementations.
This table is updated each time a new type is defined.
```erg
``` erg
provided_method_table = {
...
"foo": [Foo],
@ -31,46 +37,49 @@ provided_method_table = {
}
```
具有方法的类型为<gtr=28/><gtr=29/>。从这些中,寻找符合型的。符合判定有两种。筛型判定和记录型判定。从筛型判定开始进行。
Types that have a `.times` method are `Nat`, `Foo`. From among these, find one that matches the `{1}` type.
There are two types of conformity determination. They are sieve-type judgment and record-type judgment. This is done from the sieve type determination.
## 筛子型判定
## Sieve type determination
检查候选类型是否与类型<gtr=32/>兼容。筛型中与<gtr=33/>兼容的有<gtr=34/><gtr=35/>等。<gtr=36/><gtr=37/>等有限元的代数运算类型,如果声明为基本类型,则被归一化为筛子类型(即,<gtr=38/><gtr=39/>)。在这次的情况下,由于<gtr=40/><gtr=41/>,所以<gtr=42/><gtr=43/>是兼容的。
Check if the candidate type is compatible with the type `{1}` of `1`. The sieve types compatible with `{1}` are `{0, 1}`, `0..9`, and so on.
Finite element algebraic types such as `0..1 or 3..4`, `-1..2 and 0..3` are normalized to sieve types when declared as base types (i.e. ` {0, 1, 3, 4}`, `{0, 1, 2}`).
In this case, `Nat` is `0.._ == {I: Int | I >= 0}`, so `{1}` is compatible with `Nat`.
## 记录类型判定
## Determine record type
确认是否与候选类型为 1 的类兼容。此外,当<gtr=45/>的补丁,并且<gtr=46/>具有所有的要求属性时,也具有兼容性。
Check if the candidate type is compatible with `Int`, a class of 1.
Others that are patches of `Int` and that `Int` has all the required attributes are also compatible.
~
因此,是合适的。但是,当<gtr=48/>也符合时,根据<gtr=49/><gtr=50/>的包含关系进行判定。也就是说,选择子类型的方法。如果两者没有包含关系,则会出现编译错误(这是一种安全措施,可防止执行与程序员意图相反的方法)。为了消除错误,必须明确指定修补程序。
So `Nat` fit. However, if `Foo` also matches, it is determined by the containment relationship between `Nat` and `Foo`.
That is, subtype methods are selected.
If there is no containment relationship between the two, a compile error will occur (this is a safety measure against executing a method against the programmer's intention).
To eliminate the error, you need to specify the patch explicitly.
```erg
``` erg
o.method(x) -> P.method(o, x)
```
## 全称补丁程序方法解析
## method resolution for universal patches
定义如下补丁。
Define a patch like this:
```erg
``` erg
FnType T: Type = Patch T -> T
FnType.type = T
```
在补丁的基础上可以进行以下代码。这又将如何解决呢?
Code like the following is possible under the `FnType` patch. I wonder how this will be resolved.
```erg
``` erg
assert (Int -> Int).type == Int
```
首先,中<gtr=53/>以以下形式登录。
First, `FnType(T)` is registered in `provided_method_table` in the following format.
```erg
``` erg
provided_method_table = {
...
"type": [FnType(T)],
@ -78,9 +87,9 @@ provided_method_table = {
}
```
检查是否符合的补丁类型。此时,<gtr=55/>的补丁类型为<gtr=56/>。这符合<gtr=57/>。匹配后,进行单相化置换(取<gtr=58/><gtr=59/>的 diff。<gtr=60/>)。
`FnType(T)` is checked for matching types. In this case, `FnType(T)` patch type is `Type -> Type`.
This matches `Int -> Int`. If it fits, do monomorphization and replace (take a diff of `T -> T` and `Int -> Int`, `{T => Int}`).
```erg
``` erg
assert FnType(Int).type == Int
```
```

View file

@ -1,13 +1,17 @@
# Erg 代码如何转堆到 Python 代码中?
# How is Erg code transpiled to Python code?
准确地说Erg 代码被转堆为 Python 字节代码。但是 Python 字节码几乎可以恢复为 Python 代码,所以这里给出一个等效的 Python 代码作为例子。顺便说一下,这里的示例是优化级别较低的示例。进一步的高级优化将清除不需要生成实体的内容。
To be precise, Erg code is transpiled to Python bytecode.
However, since Python bytecode can almost be reconstructed into Python code, the equivalent Python code is used as an example here.
By the way, the example presented here is a low optimization level.
More advanced optimizations eliminate things that don't need to be instantiated.
## Record, Record type
变换成 namedtuple。有关 namedtuple 的信息,请参见。类似的功能包括 dataclass但由于自动实现和<gtr=10/>dataclass 的性能略有下降。
It will be transpiled to a namedtuple.
For namedtuple, see [here](https://docs.python.jp/3/library/collections.html#collections.namedtuple).
There is a similar function, dataclass, but dataclass has a slight performance drop due to auto-implementation of `__eq__` and `__hash__`.
```erg
``` erg
Employee = Class {.name = Str; .id = Int}
employee = Employee.new({.name = "John Smith"; .id = 100})
@ -15,7 +19,6 @@ employee = Employee.new({.name = "John Smith"; .id = 100})
assert employee.name == "John Smith"
```
```python
from typing import NamedTuple
@ -29,42 +32,39 @@ employee = Employee('John Smith', 100)
assert employee.name == 'John Smith'
```
如果可以进一步优化,它还将转换为简单的元组。
It will also be converted to a simple tuple if it can be further optimized.
## Polymorphic Type
> WIP
> WIPs
## Instant Scope
如果名称空间中不发生冲突,则只会进行弯曲和展开。像这样的名称在字节码中使用,不能与 Python 代码相对应,但如果强行表示,则会出现以下情况。
If no namespace conflicts occur, it will simply be mangled and expanded.
Names such as `x::y` are used in bytecode and cannot be associated with Python code, but if you force it to be expressed, it will be as follows.
```erg
``` erg
x =
y = 1
y + 1
y+1
```
```python
x::y = 1
x = x::y + 1
```
如果发生冲突,请定义和使用只能在内部引用的函数。
In case of conflict, define and use a function that can only be referenced internally.
```erg
``` erg
x =
y = 1
y + 1
y+1
```
```python
def _():
x = 1
x=1
y = x
return y + 1
x = _()
@ -72,20 +72,19 @@ x = _()
## Visibility
对于公共变量,它是 Python 的缺省值,因此不执行任何操作。私域变量是由 Munging 处理的。
It does nothing for public variables as it is Python's default.
Private variables are handled by mangling.
```erg
x = 1
``` erg
x=1
y =
x = 2
assert module::x == 2
```
```python
module::x = 1
y::x = 2
assert module::x == 2
y = None
```
```

View file

@ -1,35 +1,39 @@
# 归一化
# Normalization
* Erg 的类型参数规范化使用 SymPy 的 simplify 函数。
* Erg's type argument normalization is based on SymPy's simplify function.
例如,在定义时,必须不具体化类型变量和自变量而进行一致判定。等式判定自然是有界限的,目前可能的判定及其方式如下所示。
For example, when you define `concat: |T, M, N|([T; M], [T; N] -> [T; M+N])`, you can match type variables and arguments without instantiating them. Judgment must be made.
Equality judgment naturally has its limits, but the judgments that are possible at present and their methods are as follows.
* 相加/乘法对称性:
* Addition/multiplication symmetry:
`n+m == m+n`
类型变量作为字符串进行分类并正规化。
Type variables are sorted and normalized as strings.
* 加法与乘法、减法与除法的等效性:
* Equivalence of addition and multiplication, subtraction and division:
`n+n == 2*n`
归一化为Σ [c]x==c*xc 为常数)。常量放在二项式演算的左边进行正规化。
Normalize to Σ[c] x == c*x, where c is a constant.
Constants are normalized by placing them on the left side of binary operations.
* 复式等效性:
* Equality of double expressions:
`n+m+l == m+n+l == l+m+n ==...` `n+m*l == m*l+n`
`n+m+l == m+n+l == l+m+n == ...`
`n+m*l == m*l+n`
通过分类进行正规化判定。乘法、除法的程序块在加法、减法的左侧出。块之间比较最左边的类型变量进行分类。
Determined by normalizing by sorting.
Blocks for multiplication and division are placed to the left of addition and subtraction. Blocks are sorted by comparing the type variables on the leftmost side.
* 基本不公式:
* Basic inequalities:
`n > m -> m + 1 > n`
* 等式:
* Equality:
`n >= m and m >= n -> m == n`
* 不等式的推移性:
* Transitivity of inequalities:
`n > 0 -> n > -1`
`n > 0 -> n > -1`

View file

@ -32,4 +32,4 @@
* 修复特定错误的分支(如果该问题是一个错误,则代替`issue-*`创建)。
* 没有条件。
* 没有条件。

View file

@ -2,16 +2,18 @@
## debug
进入调试模式。由此,在 Erg 内部的举动被逐次记录表示出来。独立于 Rust 的标志。
Enter debug mode. As a result, the behavior inside Erg is sequentially displayed in the log.
Independent of Rust's `debug_assertions` flag.
## japanese
系统语言为日语。Erg 内的选项、帮助(如 help、copyright、license和错误显示都保证为日语。
Set the system language to Japanese.
Erg internal options, help (help, copyright, license, etc.) and error display are guaranteed to be Japanese.
## simplified_chinese
系统语言为简体中文。
Set the system language to Simplified Chinese.
## traditional_chinese
系统语言为繁体中文。
Set the system language to Traditional Chinese.

View file

@ -21,4 +21,4 @@
├─ libraryErg脚本库
├─ srcmain.rs和驱动所在目录
└─ tests测试代码
```
```

View file

@ -1,13 +1,13 @@
# 格式
# format
所有不符合以下规则的文档都是修正的对象。
Any document that does not follow the rules below is subject to correction.
* 代码注释或内部文档以这种方式编写。
* 向外部(普通用户)展示的文档要用简单易懂的语言书写。
* 文档中首次出现的术语必须同时记录定义、含义或链接。
* ()作为补充,仅用于理解正文所必需的句子,而非理解正文所必需的句子则使用脚注。
* 如果文档内容过期,则根据进行更新。
* Write code comments or internal documentation in a certain tone.
* Documents to be shown to the outside (general users) should be written more and more.
* Always include definitions, meanings, or links to terms that appear for the first time in the document.
* Use parentheses as a proviso only for sentences that are supplementary but necessary for understanding the main text, and use footnotes for sentences that are not essential for understanding the main text[<sup id="f1">1</ sup>](#1).
* If the content of the document is outdated, update it according to [this method](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362).
---
<span id="1" style="font-size:x-small">1<gtr=5/>脚注的写法参照此。<gtr=3/></span>
<span id="1" style="font-size:x-small"><sup>1</sup> See this for how to write footnotes. [](#f1)</span>

View file

@ -1,19 +1,19 @@
# 开发环境
# Development environment
## 需要安装的内容
## What you need to install
* Rust (installed with rustup)
* ver >= 1.63.0
* 2021 edition
* ver >= 1.63.0
* 2021 edition
* [pre-commit](https://pre-commit.com/)
* Python3 解释器
* Python3 interpreter
## 建议
## Recommendation
* 编辑器Visual Studio 代码
* VSCode 扩展Rust-analyzer、GitLens、Git Graph、GitHub Pull Requests and Issues、Markdown All in One、markdownlint
* OS: Windows 10/11 | Ubuntu 20.04/22.04 | MacOS Monterey
* 其他pyenvmold
* Editor: Visual Studio Code
* VSCode extensions: Rust-analyzer, GitLens, Git Graph, GitHub Pull Requests and Issues, Markdown All in One, markdownlint
* OS: Windows 10/11 | Ubuntu 20.04/22.04 | Mac OS Monterey
* Others: pyenv, mold

View file

@ -1,6 +1,6 @@
# Erg design's "Why" and Answers
## 为什么拥有所有权系统仍然同时使用GC
## 当我们有所有权系统时,为什么要与 GC 共存
因为 Erg 推出所有权系统的动机并不是为了 Rust 那样的“不依赖 GC 的内存管理”。最初,由于 Erg 是一种语言,目前使用 Python VM因此最终仍使用 GC。Erg 引入产权系统的目标是“可变状态的局部化”。在 Erg 中,可变对象具有所有权概念。这是根据共享可变状态容易成为 bug 的温床,甚至是类型安全性的侵犯(详见)来判断的。
@ -95,7 +95,7 @@ A没有那个计划。最重要的原因是如果允许定义自己的运
首先Erg 中没有变量的可变性。也就是不能重新赋值。一旦对象与一个变量关联,它将一直绑定到该变量,直到它脱离作用域并被释放。在 Erg 中,可变性是指对象的可变性。明白了这个,故事就简单了。例如,表示<gtr=14/>,但由于变量是不可重新赋值的,因此这种语法是非法的。还有一个 Erg 的设计原则是运算符没有副作用。Python 通常也是如此,但对于某些对象(如 Dict扩展赋值运算符会更改对象的内部状态。这算不上是一个很漂亮的设计。因此扩展赋值运算符被完全废弃。
## 为什么 Erg 在语法上特别对待有副作用的物体
## 为什么 Erg 在语法上特别对待有副作用的过程
副作用的局部化是代码维护的一个关键因素。
@ -103,4 +103,4 @@ A没有那个计划。最重要的原因是如果允许定义自己的运
什么情况下可以说合一化是错的一个指标是“是否会因其合一而难以看到错误信息”。Erg 设计师发现,将副作用特殊处理会使错误消息更容易阅读。
Erg 有一个强大的类型系统,但并不是所有的类型都决定了它。如果这样做了,你的下场就跟 Java 试图用类来控制一切一样。
Erg 有一个强大的类型系统,但并不是所有的类型都决定了它。如果这样做了,你的下场就跟 Java 试图用类来控制一切一样。

View file

@ -1,4 +1,4 @@
# Multilingualization of Messages
# 多语言错误信息
Erg 正在推动消息(开始、选项、文档、提示、警告、错误消息等)的多语言化。如果你不熟悉 Rust 或 Erg也可以参与此项目。请务必配合。
@ -33,7 +33,7 @@ switch_lang!(
`{name}`部分是 Rust 的格式化功能,允许你将变量的内容(`name`)嵌入到字符串中。
## Build
## 构建
现在,我们使用选项构建它。
@ -52,4 +52,4 @@ Q如果想添加自己的语言该如何替换部分目前支持
* "simplified_chinese" (简体中文)
* "traditional_chinese" (繁体中文)
如果你想添加其他语言,请提出请求。
如果你想添加其他语言,请提出请求。

View file

@ -1,23 +1,23 @@
# Rust 代码准则
# Guidelines for Rust code
## 本地规则
## local rules
* 用于调试的输出使用(释放时所需的输出处理也使用<gtr=2/>等)。
* 未使用或内部(专用和仅用于特定功能)的变量方法以一个开头。如果想避免与保留字的冲突,则在后面加上一个。
* Use `log!` for output for debugging (use `println!` etc. for output processing that is also necessary for release).
* Unused or internal variables/methods (private and used only for specific functions) must be prefixed with `_`. If you want to avoid conflicts with reserved words, add one `_` to the end.
## 鼓励代码
## Recommended code
* 定义并使用特定于域的 Enum而不是数字枚举和 bool。
* 存取修饰符为必要的最小限度。即使公开时也优先使用和<gtr=6/>
* for 表达式中的 iterable 对象显式转换为迭代器(,而不是<gtr=7/>)。
* 延迟评估。例如,当不是文字时,使用<gtr=11/>而不是<gtr=10/>
* Define and use domain-specific Enums instead of numeric enumerations or bools.
* Keep access modifiers to a minimum. Prioritize using `pub(mod)` or `pub(crate)` even when publishing.
* Convert an iterable object in a for expression explicitly to an iterator (`for i in x.iter()` instead of `for i in x`).
* Lazy evaluation. For example, if `default` is non-literal, use `unwrap_or_else` instead of `unwrap_or`.
## 不鼓励的代码
## Code not encouraged
* 经常使用 return type overloading。具体来说经常使用不明确的的代码。这是因为型推论结果有时违反直觉。在这种情况下建议使用<gtr=13/>代替。
* 经常使用。这实质上引起了与继承相同的问题。
* Make heavy use of return type overloading. Specifically code that uses a lot of non-obvious `.into`. This is because type inference results can be counter-intuitive. In this case it is recommended to use `from` instead.
* Make heavy use of `Deref`. This effectively poses the same problem as inheritance.
## 根据上下文判断不同的代码
## Code that makes decisions based on context
* 定义未使用的 helper 方法。
* 经常使用,<gtr=16/>。在某些情况下,有些人别无选择,只能这样做。
* Define unused helper methods.
* Use `unwrap` and `clone` a lot. In some cases there is nothing better than doing so.

View file

@ -1,12 +1,13 @@
# 术语词典
# Glossary
## 符号
## symbol
### &excl;
过程或附加在标识符末尾的标记,以指示其为可变类型。或者变量运算符。
A marker added to the end of an identifier to indicate that it is a procedure or variable type.
Or the mutating operator.
### ../syntax/00_basic.md/# 注释
### [&#35;](../syntax/00_basic.md/# comment)
### $
@ -14,7 +15,7 @@
### &
### (single quote)
### &prime; (single quote)
### &lpar;&rpar;
@ -146,7 +147,7 @@
## L
### [秩 1 多相]
### let-polymorphism -> [rank 1 polymorphism]
### [log]
@ -190,7 +191,7 @@
### ref
### ref!
### ref&excl;
### [Result]
@ -208,7 +209,7 @@
## T
### Trait
### Traits
### [True]
@ -230,602 +231,609 @@
## Z
## 阿行
## A line
### 断言
### [Assertion]
检查代码中的条件是否成立(通常是在运行时)。使用函数等进行操作。
To check (typically at runtime) whether a condition is true in code. This is done using the `assert` function, etc.
```erg
``` erg
sum = !0
for! 0..10, i =>
sum.add! i
sum.add!i
assert sum == 55
```
### 值对象
### Value Object
在 Erg 中,与基本对象相同。编译时可以进行评价,拥有不言而喻的比较方法。
In Erg, equivalent to base object. It can be evaluated at compile time and has a trivial comparison method.
### 附着面片../syntax/29_decorate.md#attach
### [Attachment patch](../syntax/29_decorator.md#attach)
为 Tracet 提供标准实现的补丁程序。
A patch that gives the trait a standard implementation.
### 即席多相->
### Ad hoc polymorphism -> [No overloading](../syntax/type/overloading.md)
所谓超载的多相。
Polymorphism with so-called overloading.
### 属性-属性
### Attribute -> [attribute]
标识符中的<gtr=9/>部分。
The `y` part in the `x.y` identifier.
### 安利
### Arity
运算符使用多少个操作数。
How many operands the operator takes.
### 依赖关系../syntax/type/dependent_type.md
### [Dependent type](../syntax/type/dependent_type.md)
以值(通常为非类型)为参数的类型。
A type whose argument is a value (idiomatically, not a type).
### 可变体-> 不可变
### immutable -> [immutable]
表示目标保持不变。在其他语言中,变量也具有可变/可变特性,但在 Erg 中,变量都是可变的。
Indicates that the target will not change.
Variables in other languages are also immutable/mutable, but in Erg all variables are immutable.
### 参数-> 参数
### arguments -> [arguments]
### 实例
### instance
类创建的对象。类类型的元素。
An object created by a class. An element of class type.
### 即时块(../syntax/00_basic.md# 表达式分隔符)
### [instant block](../syntax/00_basic.md#expression separator)
```erg
``` erg
x =
y = f(a)
z = g(b, c)
y + z
z = g(b,c)
y+z
```
### 索引
### index
形式为,或其中<gtr=11/>的部分。称为 Indexable 对象。
of the form `x[i]`, or the `i` part thereof. We call `x` an Indexable object.
### 缩进../syntax/00_basic.md# 缩进
### [indent](../syntax/00_basic.md#indent)
靠空格使句子向右靠。缩进。Erg 通过缩进来表现块。这叫做越位规则。
Align text to the right by moving toward spaces. Indentation.
Ergs represent blocks by indentation. This is called the offside rule.
### 别名
### Aliases
别名。
Alias.
### 错误
### error
规范规定的异常状态。
Abnormal conditions defined in the specification.
* [エラーハンドリング]
* [Error handling]
### 运算符../syntax/06_operator.md
### [operator](../syntax/06_operator.md)
将运算应用于操作数的对象。或表示对象的符号。
An object that applies an operation to its operands. or a symbol denoting that object.
* [演算子の結合強度]
* [operator binding strength]
### 覆盖
### Override
用子类覆盖超类的方法。在 Erg 中,覆盖时必须安装装饰器。
Overriding superclass methods in subclasses.
In Erg you have to add `Override` decorator when overriding.
### 禁止过载(../syntax/type/overloading.md
### [No overloading](../syntax/type/overloading.md)
### 越位规则->
### Offside rule -> [indent](../syntax/00_basic.md#indent)
### 对象
### [object]
* 面向对象
* Object-orientation
### 操作数->
### operand -> [operand](../syntax/06_operator.md)
### 操作员->
### operator -> [operator](../syntax/06_operator.md)
## 家行
## Ka line
### 卡印(../syntax/type/advanced/kind.md
### [kind](../syntax/type/advanced/kind.md)
所谓模子的模子。
Types of so-called types.
### 可见性
### [visibility]
标识符是否可从外部(范围外或单独模块、单独软件包)引用的性质。
The property of whether an identifier can be referenced externally (out of scope, or in another module or package).
### 类型
### [type]
要对项进行分组的对象。
An object that groups terms.
* [型指定]
* 清除类型(../syntax/type/advanced/erasure.md
* [型推論]
* 类型注释../syntax/type/conv_type.md
* [型引数]
* 添加类型(../syntax/type/advanced/erasure.md
* 类型变量(../syntax/type/type_variable.md
* [型制約]
* [type specification]
* [type erasure](../syntax/type/advanced/erasure.md)
* [type inference]
* [type annotation](../syntax/type/conv_type.md)
* [type argument]
* [type addition](../syntax/type/advanced/erasure.md)
* [type variable](../syntax/type/type_variable.md)
* [type constraint]
### 保护
### [Guard]
### 封装
### Encapsulation
隐藏实现细节。
Hiding implementation details.
### 变量
### [variable]
不可变。
Must not be immutable.
* [可変オブジェクト]
* [可変型]
* [可変参照]
* [可変配列]
* [可変長引数]
* [mutable object]
* [variable]
* [variable reference]
* [variable array]
* [variable arguments]
### 函数../syntax/04_function.md
### [function](../syntax/04_function.md)
没有副作用的子程序。
A subroutine with no side effects.
* 函数型编程(../syntax/23_scop.md# 避免变量状态函数型编程)
* [Functional programming](../syntax/23_scope.md#Avoiding mutable stateFunctional programming)
### 基本类型
### base type
### 记名的
### nominative
通过名称而不是对称结构来区分。
Distinguish by name rather than by symmetrical structure.
* [记名型]->
* [記名化]
* 记名部分类型../syntax/type/05_nst_vs_sst.md
* [named type] -> [class](../syntax/type/04_class.md)
* [Annunciation]
* [nominal subtype](../syntax/type/05_nst_vs_sst.md)
### 捕捉-> 闭包
### capture -> [closure]
### 协变
### [covariant]
在 Erg 中,当时,如果<gtr=19/>,则<gtr=20/>为协变。
In Erg, if `T <: U` then `K(T) <: K(U)` then `K` is said to be covariant.
### 关键字参数
### [keyword arguments]
函数调用形式中的<gtr=22/>。实际自变量可以用假自变量名而不是顺序指定。
`k` in the form of function call `f(k: v)`. You can specify actual arguments by formal argument name instead of by order.
### 空集->[{}]
### empty set -> [{}]
### 区间
### section
* 间隔类型(../syntax/type/11_interval.md
* 区间运算符
* [Interval type](../syntax/type/11_interval.md)
* interval operator
### 嵌入
### Embedded
未在.er 文件中实现的 Erg 标准 API。
Erg standard APIs not implemented in .er files.
### 类../syntax/type/04_class.md
### [class](../syntax/type/04_class.md)
具有继承功能的结构和抽象数据类型。在 Erg 中是为了实现记名式分型以及覆盖的类型。在其他语言中也有承担模块和型的责任和义务的情况,在 Erg 中,模块是模块对象,型是型对象承担其责任和义务。
Structure/abstract data type with inheritance function. In Erg, it is a type to implement named subtyping and overriding.
In Erg, modules are the responsibility of module objects, and types are the type object, while other languages may be responsible for modules and types.
### 闭合
### [Closure]
### 全局变量
### [global variables]
### 克隆
### [Clone]
### 继承
### [inheritance](../syntax/type/07_inheritance.md)
定义以某个类为上级集合的类。继承源的类称为超类,继承目标的类称为子类。子类具有超类的所有功能。
To define a class that is a superset of another class.
The class that inherits is called the superclass, and the class that inherits is called the subclass.
A subclass has all the functionality of its superclass.
### 高阶
### high floor
* 高阶../syntax/type/advanced/kind.md
* 高阶型
* 高阶函数
* [higher-order kind](../syntax/type/advanced/kind.md)
* higher order type
* Higher-order functions
### 公共变量
### [public variables]
### 结构子类型
### [structural subtype]
### ~~ 向后参照 ~~~->[向前参照]
### ~~back reference~~ -> [back reference]
### 复制
### [copy]
### 注释
### comment
### 集合../syntax/10_array.md
### [Collection](../syntax/10_array.md)
### 冒号->[]
### Colon -> [:]
### 构造函数(../syntax/type/04_class.md
### [constructor](../syntax/type/04_class.md)
### 集装箱
### container
### 编译器
### Compiler
### 编译时计算../syntax/04_function.md# 编译时函数
### [compile-time computation](../syntax/04_function.md#compile-time function)
### 逗号->[]
### comma -> [,]
## 差行
## sa line
### 递归
### recursion
指自己。
Refer to yourself.
* 递归型
* 递归函数../syntax/04_function.md# 递归函数
* recursive
* [Recursive function](../syntax/04_function.md#Recursive function)
### 下标-> 索引
### subscript -> [index]
### 多相子类型(../syntax/type/overloading.md
### [subtyping polymorphism](../syntax/type/overloading.md)
多相分型。子类型是指在类型中与集合的包含关系相对应的类型。
Polymorphism with subtyping. Subtyping corresponds to set containment in types.
### 子程序
### Subroutine
模块化处理的对象。Erg 中函数、过程和方法的通用名称。
An object that modularizes processing. A generic term for functions, procedures, and methods in Erg.
### 参考(../syntax/18_memory_management.md# 借用)
### [reference](../syntax/18_memory_management.md#borrowed)
* 引用对象
* 参照计数 (RC) ../syntax/18_memory_management.md# 内存管理)
* 参考等效性->
* reference object
* [Reference counting (RC)](../syntax/18_memory_management.md#memory management)
* Reference equality -> [side effect](../syntax/07_side_effect.md)
### 标识符(../syntax/02_variable.md/# 赋值)
### [identifier](../syntax/02_variable.md/# assignment)
### 签名
### signature
* 类型签名
* type signature
### 词典../syntax/11_dict.md
### [dict](../syntax/11_dict.md)
### 自然数->Nat
### [natural number] -> [Nat]
### 通用->[全称类型]
### Generics -> [Generic]
### 发电机
### Generator
### 投影类型
### [projective type]
### 借用->
### borrow -> [reference](../syntax/18_memory_management.md#borrowed)
### 阴影(../syntax/02_name.md# 变量)
### [shadowing](../syntax/02_name.md# variables)
在内部作用域中定义一个同名的变量,并覆盖该变量的引用。
To override a reference to a variable by defining a variable with the same name in an inner scope.
### 种子->
### kind -> [kind](../syntax/type/advanced/kind.md)
大致是个模子。
Roughly the type of type.
### 集-> 集
### [set] -> [set]
在 Erg 中是 Set 对象。
In Erg, it means a Set object.
### 谓语
### Predicate
* [述語関数]
* [predicate function]
返回布尔类型的函数。
A function that returns a bool type.
### 条件分歧
### Conditional branch
### 所有权
### [Ownership]
关于对象唯一性的概念。如果拥有对象的所有权,则可以对对象进行可变引用。
The concept of object uniqueness.
If you have ownership of an object, you can take a mutable reference to it.
### 真伪类型-> 布尔
### Boolean -> [Bool]
### 单吨
### Singleton
从只能生成一个实例的类生成的实例。也指确保只生成一个类实例的设计模式。
An instance created from a class that can create only one instance. A design pattern that ensures that only one instance of a class is created.
### 符号->
### [Symbol] -> [Identifier](../syntax/02_name.md)
* [シンボル化]
* [symbolization]
### 脚本../syntax/00_basic.md# 脚本
### [script](../syntax/00_basic.md# script)
描述 Erg 程序的文件。
A file containing an Erg program.
### 范围
### Scope
变量管理中的单位。外侧的范围不能参照存在于内侧范围的变量。另外,脱离范围时,参照点数为 0 的对象被释放。
Units in variable management. An outer scope cannot refer to a variable that exists in an inner scope.
Objects with a reference count of 0 are freed when the scope exits.
### 跨页运算符-> 展开赋值
### spread operator -> [expansion assignment]
### 切片../syntax/10_array.md# 切片
### [slice](../syntax/10_array.md#slice)
以形式生成的表示数组子串的对象。
An object representing a subsequence of the array, generated in the form `x[a..b]`.
### 控制字符
### control characters
### 整数-> 输入
### [Integer] -> [Int]
自然数加负数的集合。
A set of natural numbers plus negative numbers.
### 集../syntax/12_set.md
### [set](../syntax/12_set.md)
### 分号->[]
### Semicolon -> [;]
### 声明../syntax/03_declaration.md
### [Declaration](../syntax/03_declaration.md)
显式设置变量类型。
Explicitly type variables.
### 全称
### Full name
* 全称类型->
* 封闭全称类型
* 打开的全称类型
* 全称函数-> 多相关数
* 全称量化
* universal type -> [polymorphic type](../syntax/type/quantified.md)
* closed universal
* Open Universal
* universal function -> polycorrelation function
* universal quantification
### 前缀运算符
### prefix operator
以格式应用的运算符<gtr=30/>
Operator `∘` applied in the form `∘x`.
### 互相的递归
### mutual recursion
### 下标-> 索引
### subscript -> [index]
### 属性
### [attributes]
* [属性的部分型]
* [attribute subtype]
## 多行
## Ta line
### 代数../syntax/02_name.md
### [algebra](../syntax/02_name.md)
* 代数类型(../syntax/type/13_algebraic.md
* 代数数据类型
* [algebraic type](../syntax/type/13_algebraic.md)
* algebraic data types
### 赋值../syntax/02_variable.md/# 赋值
### [assignment](../syntax/02_variable.md/#assignment)
### 多重
### Multiple
* 多重继承(../syntax/type/07_inheritance.md/# 禁止多重继承)
* 多重赋值
* 多重定义-> 禁止过载
* [Multiple inheritance](../syntax/type/07_inheritance.md/#Prohibition of multiple inheritance)
* Multiple assignment
* Overload -> [No overloading]
### 多相
### Polymorphism
* 多相类型(../syntax/type/quantified.md
* 多相关数
* [polymorphic type](../syntax/type/quantified.md)
* polycorrelation coefficient
### 多态-> 多态
### polymorphism -> [polymorphism]
### 烤鸭打字
### duck typing
### 元组(../syntax/11_tuple.md
### [tuple](../syntax/11_tuple.md)
### 单相
### Single-phase
* 单相化
* 单相型
* 单相关数
* Single phase
* Single-phase type
* Single correlation coefficient
### 延迟初始化
### [Lazy initialization]
### 抽出赋值
### Extraction Assignment
### 抽象语法树->[AST]
### Abstract syntax tree -> [AST]
### 中置运算符
### Infix operator
以格式应用的运算符。
The operator `∘` applied in the form `x∘y`.
### 常量../syntax/02_name.md/# 常量
### [constant](../syntax/02_name.md/#constant)
可执行的、编译时可评估的代数。
Immutable, compile-time evaluable algebra.
* 常量类型(../syntax/type/advanced/const.md
* 常量表达式(../syntax/type/advanced/const.md
* [constant type](../syntax/type/advanced/const.md)
* [constant expression](../syntax/type/advanced/const.md)
### 定义
### [definition]
分配与变量对应的对象。
Allocating an object corresponding to a variable.
### 授课属性
### Provided Attributes
可用作 API 的属性。特别是由trait自动实现的属性。
Attributes available as API. Especially attributes auto-implemented by traits.
### 应用
### [Apply]
将参数传递给函数对象以获得评估结果。
To pass an argument to a function object and get the evaluation result.
### 装饰器../syntax/29_decorate.md
### [decorator](../syntax/29_decorator.md)
```erg
``` erg
@deco
f x = ...
```
的语法糖,或者。大约等于。本身只是一个高阶子程序。
syntactic sugar, or `deco`. Roughly equal to `_f x = ...; f = deco _f`. `deco` itself is just a higher-order subroutine.
### 析构
### destructor
销毁对象时调用的方法。
Method called when the object is destroyed.
### 过程->
### procedure -> [procedure](../syntax/08_procedure.md)
读取和写入可变状态的子程序。有时会解释程序根据调用顺序的不同,程序的执行结果也会发生变化,但如果说的是可换性的话,这是错误的。例如,作为函数子类型的运算符一般不是可换的。
A subroutine that reads and writes mutable state.
It is sometimes said that the execution result of a program can change depending on the order in which the procedures are called, but this is incorrect if we are talking about commutativity.
For example, operators that are subtypes of functions are generally not commutative.
### 缺省参数../syntax/04_function.md/# 缺省参数 default-parameters
### [default arguments](../syntax/04_function.md/#default arguments default-parameters)
通过为虚拟自变量指定缺省值,调用时可以省略实际自变量指定的功能。
A function that allows you to omit the specification of actual arguments at the time of calling by specifying default values for formal arguments.
### 展开
### Expand
* [展開演算子]
* [展開代入]
* [expansion operator]
* [expansion assignment]
### 特殊格式(../syntax/../API/special.md
### [special format](../syntax/../API/special.md)
不能传递给实际参数的对象。
An object that cannot be passed as an actual argument.
### 匿名函数->
### anonymous function -> [anonymous function](../syntax/20_lambda.md)
由未命名函数运算符生成的函数对象。不用定义名字就能使用。
A function object created by the anonymous function operator `->`. Can be used without defining a name.
### 点运算符()->[属性引用]
### dot operator (`.`) -> [attribute reference]
### 顶部
### Top
* 顶部类型-> 结构对象
* 顶级-> 对象
* Top type -> [Structural Object]
* Top class -> [Object]
### TRAIT../syntax/type/03_trait.md
### [trait](../syntax/type/03_trait.md)
## 标题
## na line
### 内涵符号../syntax/27_comprehension.md
### [Comprehension](../syntax/27_comprehension.md)
### 中置算子 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### ~~Infix operator~~ -> [Infix operator]
### 名称空间
### [namespace]
## 派系
## is a line
### 阵列../syntax/10_array.md
### [Array](../syntax/10_array.md)
### 派生类型(../syntax/type/variances.md/# 用户定义类型的退化)
### [derived type](../syntax/type/variances.md/# user-defined type variations)
### 图案(匹配)../syntax/26_pattern_matching.md
### [pattern (match)](../syntax/26_pattern_matching.md)
### 软件包../syntax/33_package_system.md
### [package](../syntax/33_package_system.md)
### 哈希映射->
### hashmap -> [dict](../syntax/11_dict.md)
### 面片../syntax/type/07_patch.md
### [patch](../syntax/type/07_patch.md)
### 公共变量->
### public variables -> [public variables](../syntax/19_visibility.md)
### 参数->
### parameter -> [argument](../syntax/04_function.md)
### 参数化多相(../syntax/type/overloading.md
### [Parametric Polymorphism](../syntax/type/overloading.md)
### 反变(../syntax/type/advanced/variance.md
### [contravariant](../syntax/type/advanced/variance.md)
### 比较
### Compare
* [比較演算子]
* [比較可能型]
* [comparison operator]
* [comparable type]
### 私有变量../syntax/19_visibility.md
### [private variable](../syntax/19_visibility.md)
### 标准
### standard
* 标准输出
* 标准输入
* 标准库
* standard output
* standard input
* standard library
### 副作用../syntax/07_side_effect.md
### [side effects](../syntax/07_side_effect.md)
代码不能读取或写入外部可变状态。
Code should/not read/write external mutable state.
### 复数->
### complex number -> [Complex]
### 浮点数-> 浮点
### [Float] -> [Float]
### 专用变量-> 专用变量
### private variables -> [private variables]
### 布尔代数-> 布尔
### Boolean algebra -> [Bool]
### 程序../syntax/08_procedure.md
### [procedure](../syntax/08_procedure.md)
### 参数(../syntax/04_function.md
### [arguments](../syntax/04_function.md)
### 部分类型-> 子类型
### Partial Typing -> [Subtyping]
### 不变
### [immutable]
在 Erg 中,对象不改变其内容。
In Erg, an object should never change its contents.
* [不変オブジェクト]
* [不変型]
* [不変参照]
* [immutable object]
* [immutable type]
* [immutable reference]
### 筛型(../syntax/type/12_refinement.md
### [sieve type](../syntax/type/12_refinement.md)
###
### [block]
### 分解赋值
### Destructuring assignment
### 变量../syntax/02_variable.md
### [variable](../syntax/02_variable.md)
### 底部
### bottom
* 底部->[{}]
* 底部类->Never
* bottom type -> [{}]
* Bottom class -> [Never]
### 多态
### [Polymorphism]
## 真行
## ma line
### 前缀运算符 ~~~~~~ 前缀运算符
### ~~ prefix operator ~~ -> prefix operator
### 标记类型../syntax/type/advanced/marker_trait.md
### [marker type](../syntax/type/advanced/marker_trait.md)
### 无名函数../syntax/21_lambda.md
### [anonymous function](../syntax/21_lambda.md)
### 可变-> 可变
### mutable -> [mutable]
### 移动
### [move]
### 方法
### methods
### 元字符
### Metacharacters
### 模块(../syntax/24_module.md
### [module](../syntax/24_module.md)
### 字符串->Str
### [String] -> [Str]
* 字符串插值(../syntax/01_literal.md/#Str 文字)
* [String interpolation](../syntax/01_literal.md/#Str literal)
### 返回值
### Return value
## 夜行
## or line
### 幽灵类型(../syntax/type/advanced/phantom.md
### [phantom type](../syntax/type/advanced/phantom.md)
### 请求属性
### Request Attributes
### 元素
### [element]
### 调用
### [call]
## 罗列
## Ra line
###
### [Library]
### 拉姆达公式->
### lambda expression -> [anonymous function](../syntax/20_lambda.md)
### 等级
### rank
* 通道 2 多相../syntax/type/advanced/rank2type.md
* [rank2 polymorphism](../syntax/type/advanced/rank2type.md)
### 文字(../syntax/01_literal.md
### [literal](../syntax/01_literal.md)
* 文字标识符(../syntax/18_naming_rule.md/# 文字标识符)
* [literal identifier](../syntax/18_naming_rule.md/#literal identifier)
### 量化(../syntax/type/quantified.md
### [quantified](../syntax/type/quantified.md)
### 布局(../syntax/type/mut.md
### [Layout](../syntax/type/mut.md)
### 枚举类型(../syntax/type/10_enum.md
### [enum](../syntax/type/10_enum.md)
### 记录../syntax/12_record.md
### [record](../syntax/12_record.md)
* [レコード型]
* 记录多相-> 列多相
* [record type]
* Record Polymorphism -> [Column Polymorphism]
### 列多相
### [column polymorphism]
### 局部变量../syntax/19_visibility.md
### [local variables](../syntax/19_visibility.md)
## 和行
## line
### 通配符
### Wildcard

View file

@ -1,80 +1,56 @@
# 术语统一
# Unification of terminology
## 可见性、可见性
## Accessibility, Visibility
使用“Visibility可见性”。
Use Visibility.
## 完全(非、补)
## Type bound, Type constraint
使用否定类型。Complement 的结果不一定是 Not 型。
A list of predicate expressions given to quantified and refinement types. Use type bounds.
## Diff差分型、排除型、直差型
## subroutines, routines, subprograms
使用排除类型。Diff 的结果不一定是 Not 型。
Use subroutines.
## Intersection交集、交集、笛卡尔
## Referentially transparent/not, with/without side effects
使用交叉类型。不使用笛卡儿积型。这是因为也有将元组视为笛卡儿积型的用法。但是,从属性部分型的观点来看,是与 Erg 的 And 型本质上等价的概念。另外Intersection 的结果不一定是 And 型。例如。
Use with/without side effects.
## Nominal subtyping 的翻译
## identifiers, algebra, variables, names, symbols
虽然有记名的/名目的/标称的部分定型,但是使用记名的部分定型。
In its original meaning,
## Ratio 型译词
* Symbol: Characters (except symbols, control characters, etc.) that are solid-written in source code that are not string objects (not enclosed in ""). Symbols exist as primitive types in Ruby, Lisp, etc., but they are not treated as objects in Erg.
* Identifier: A symbol that (and can) refer to some object, not a reserved word. For example, in Python class and def cannot be used as identifiers. Since Erg has no reserved words, all symbols can be used as identifiers except some symbols.
* Name: Almost same meaning as identifier. It is sometimes used synonymously with algebra in Erg.
* Algebra name: equivalent to identifier in Erg. In C, function names are identifiers, not algebraic names. "Algebra" refers to the language feature itself that allows you to assign objects with `=` (variable assignment operator) or `=` (constant assignment operator).
使用有理数型。由于 Float 是单独提供的,所以不称为浮点数型。
## Union合并、直和
使用合并类型。Union 的结果不一定是 Or 型。
## 类型边界Type bound、类型约束Type constraint
量化型、筛子型所给谓词式的列表。使用类型边界。
## 子程序,例程,子程序
中描述的相应参数的值。
## 参照透明/不透明,有/无副作用
使用有/无副作用。
## 标识符、代数、变量、名称、符号
原来的意思是,
* 符号Symbol非字符串对象未括在“”中的纯文本源代码字符符号、控制字符等除外。Ruby 和 Lisp 等中作为基本类型的符号存在,但在 Erg 中不被作为对象处理。
* 标识符Identifier指向也可以某个对象的符号而不是保留字。例如在 Python 中class 和 def 不能作为标识符使用。由于 Erg 中没有保留字,所以除去一部分符号的所有符号都可以作为标识符使用。
* 名称Name几乎等同于标识符。在 Erg 中也有与代数相同的意思使用。
* 代数名Algebra name在 Erg 中等同于标识符。在 C 语言中,函数名是标识符,但不是代数名。“代数”是指能够用(变量赋值运算符)或<gtr=4/>(常量赋值运算符)赋值对象的语言功能本身。
```erg
代数名 <: (名前 == 識別子) <: シンボル
変数 + 定数 == 代数
``` erg
algebraic name <: (name == identifier) <: symbol
variable + constant == algebra
```
但是,本来应该被称为“代数”的多被称为“变量”。这是数学术语的影响。值的内容可能变化的变量是可互斥变量,值的内容不变的变量是可互斥变量。另外,常数一定是可变的。
However, what should be called "algebra" is often called "variable". This is the effect of mathematical terminology.
A variable whose value content can change is a mutable variable, and a variable whose value content does not change is an immutable variable.
Note that constants are always immutable.
Erg 中代数名,不使用名称,用标识符统一。但是,一般来说,的<gtr=6/>被称为“变量 v”“Variable v”<gtr=7/><gtr=8/>被称为“常数 C”“Constant C”
Algebraic names and names are not used in Erg, and uniform identifiers are used.
However, in general, `v` with `v = 1` is called "Variable v", and `C` with `C = 1` is called "Constant C". .
## 属性、字段和特性
## Attribute, Field, Property
属性,使用属性。顺便一提,记录是指在没有类的情况下可以定义具有要素属性的对象的功能。
Use attributes. By the way, a record is a function that can define an object with element attributes without a class.
## 应用Application、调用Call
## Application, Call
通过向子程序对象提供参数来获得结果。使用调用Call。因为 Application 具有“应用软件”的用法。
Giving arguments to a subroutine object and getting a result.
Use Call. This is because Application has a usage of "application software".
## 数组、列表
## Array, List
使用 Array。这是因为 Erg 的排列通常是在存储器上连续排列的。List 指的是所谓的连接列表,或者作为 Python 的数据类型的列表。
Use Arrays. Erg arrays are (generally) contiguous in memory.
List refers to a so-called linked list, or a list as a Python data type.
## 过程,过程
## lambda functions, lambda expressions, anonymous functions
与过程一致。子例程是函数和运算符、过程和方法的总称。Callable 是安装了的全部。
## Lambda 函数、Lambda 表达式、匿名函数、匿名函数
统一为无名函数。英语中为了缩短字数可以使用 Lambda但正式名称是 Anonymous function。另外Erg 的无名函数不是匿名的,所以不使用匿名函数。
Unify with anonymous functions. In English, Lambda can be used to shorten the number of characters, but the official name is Anonymous function.

View file

@ -1,27 +1,37 @@
# Erg FAQ
本常见问题解答适用于一般 Erg 入门用户。请参阅以了解具体的(常见的)技术问题,或参阅<gtr=2/>以了解语法的决定(为什么出现这种语法)。
This FAQ is intended for the general Erg beginner.
For individual (common) technical issues, please refer to [here](./faq_technical.md) for individual (common) technical issues, and
[Here](./dev_guide/faq_syntax.md) for more information.
## Erg 是 Python 兼容语言是什么意思?
## What does it mean that Erg is a Python compatible language?
~~AErg 的执行系统 EVMErg VirtualMachineEVM执行由 Python 字节代码扩展而成的 Erg 字节代码。这是在 Python 字节码中引入的静态定型系统(在不带参数的指令中引入参数,在空号中实现专有指令)。这使得 Erg 能够无缝调用 Python 的代码,并实现快速执行。~~
~~A: Erg's executable system, EVM (Erg VirtualMachine), executes Erg bytecode, which is an extension of Python bytecode. It introduces a static typing system and other features into the Python bytecode (such as introducing arguments to instructions that do not take arguments, and implementing unique instructions in the free numbers). This allows Erg to call Python code seamlessly and execute it fast.~~
Erg 脚本将转换成 Python 字节码。也就是说,它与 Python 在同一解释器上运行。最初,我们计划开发一个由 Python 解释器CPython扩展而成的向上兼容处理系统并将其与编译器合并为“Erg”但由于处理系统的开发远远落后于编译器因此我们决定只先公开编译器。现在处理系统正在积极开发中。
A: Erg code is transpiled into Python bytecode. That is, it runs on the same interpreter as Python. Originally, we planned to develop a Cpython-compatible interpreter, and to combine it with the compiler to form "Erg". However, since the development of the processing system has lagged far behind that of the compiler, we have decided to release only the compiler in advance (But the interpreter is still under development).
## Erg 受到了什么语言的影响?
## What languages have influenced Erg?
双手也受到无数种语言的影响,其中受影响特别强烈的是 Python/Rust/Nim/Haskell。Python 继承了许多与越位规则兼容的语义学Rust 继承了面向表达式和traitNim 继承了过程Haskell 继承了函数型编程相关的功能。
We have been influenced by more languages than we can count on both hands, but Python, Rust, Nim, and Haskell have been the strongest influences.
We inherited many semantics from Python, expression-oriented and trait from Rust, procedures from Nim, and functional programming-related features from Haskell.
## 可以调用 Python 的语言包括 Julia。你为什么做 Erg
## Languages that can call Python include Julia. Why did you create Erg?
Erg 的一个设计动机是,他想要一种语言,既易于使用,又具有强大的类型系统。即具有类型推理、卡印、依赖性等的语言。虽然 Julia 可以进行类型化,但它实际上是一种动态的类型化语言,不能提供静态类型化语言的编译时错误检测优势。
A: One of the motivations for Erg's design was to have a language that is easy to use, yet has a powerful type system. That is, a language with type inference, Kind, dependent types, etc.
Julia can be typed, but it is really a dynamically typed language and does not have the compile-time error detection benefits of statically typed languages.
## Erg 支持多种样式,包括函数型编程和面向对象编程。这是不是与 Python 的“There should be one-and preferably only one--obvious way to do it.”背道而驰?
## Erg supports multiple styles of programming, including functional and object-oriented programming. Isn't this contrary to Python's "There should be one --and preferably only one-- obvious way to do it."?
A在 Erg 中这个词可以理解成更狭隘的意思。例如Erg API 通常没有别名。在这个意义上Erg 是“only one way”。在更大的意义和框架中如函数类型或 OOP只有一种方法不一定会带来便利。例如JavaScript 有多个库来帮助创建可转换程序,而 C 语言有多个垃圾回收库。但是,如果有多个库来执行这些基本功能,不仅会占用选择时间,而且会在使用不同库的代码之间进行集成时产生明显的困难。即使是纯函数语言 Haskell 也有支持面向对象的库。如果没有程序员,他们就会自己创造出来。那样的话,我认为还是按标准提供比较好。这也符合 Python 的“Battery included”。
A: In Erg, the term is taken in a more narrow context. For example, there are generally no aliases in the Erg API; Erg is "only one way" in this context.
In a larger context, such as FP or OOP, having only one way of doing things is not necessarily a convenience.
For example, JavaScript has several libraries to help create immutable programs, and C has several libraries for garbage collection.
However, having multiple libraries for even such basic features not only takes time to select, but also creates significant difficulties in integrating code that uses different libraries.
Even in Haskell, a purely functional language, there are libraries that support OOP.
If programmers don't have some stuffs, they will create them on their own. So, we think it would be better to provide them as a standard.
This also fits with Python's "Battery included" concept.
## Erg 名字的由来是什么?
## What is the origin of the name Erg?
名称来源于 cgs 单位制中能量的单位 erg。这是一种双重混合语言它是一种人类工程学ergonomic语言为程序员提供能量虽然是后缀
It is named after the unit of energy erg in the cgs unit system. It is a double meaning: an ergonomic language that gives programmers energy.
虽然还有一些其他候选但由于它们最短Ruby 的作者 Matz 说,语言的名称越短越好),并且具有相应的高格格不入性,因此决定了这一点。
There were several other candidates, but this was chosen because it is the shortest (according to Matz, the developer of Ruby, the shorter the better for a language name) and has a reasonably high googlability.

View file

@ -1,25 +1,34 @@
# 技术常见问题解答
# Technical FAQ
本节回答了使用 Erg 语言的技术问题。即以“What”、“Which”开头的问题以及可以回答“Yes/No”的问题。
关于根本语法的决定,请参阅,关于为什么创建这种语言,如何实现这种功能等更大的话题,请参阅<gtr=2/>
This section answers technical questions about using the Erg language. In other words, it contains questions that begin with What or Which, and questions that can be answered with Yes/No.
## Erg 没有异常机制吗?
For more information on how the grammar was determined, see [here](./dev_guide/faq_syntax.md) for the underlying syntax decisions, and [here](./dev_guide/../faq_general.md).
A没有。Erg 使用类型代替。有关为什么 Erg 没有异常机制的信息,请参见<gtr=4/>
## Is there an exception mechanism in Erg?
## Erg 没有与 TypeScript 中的 Any 相对应的类型吗?
A: No. Erg uses the `Result` type instead. See [here](./dev_guide/faq_syntax.md) for why Erg does not have an exception mechanism.
A没有。所有对象至少属于类但此类型只提供最少的属性不能像 Any 那样随心所欲。<gtr=6/>类通过动态检查(如<gtr=7/>)转换为所需的类型。它与 Java 中的<gtr=8/>类似。在 Erg 的世界里,不会出现像 TypeScript 那样追寻 API 定义的结果是 Any 的绝望和混乱。
## Does Erg have a type equivalent to TypeScript's `Any`?
## Never{}NoneNotImplementedEllipsis 有什么不同?
A: No, there is not. All objects belong to at least the `Object` class, but this type only provides a minimal set of attributes, so you can't do whatever you want with it like you can with Any.
The `Object` class is converted to the desired type through dynamic inspection by `match`, etc. It is the same kind of `Object` in Java and other languages.
In the Erg world, there is no chaos and hopelessness like in TypeScript, where the API definition is ``Any''.
A类型为“不可能发生”。生成运行时错误的子例程返回类型为<gtr=11/>的合并类型)。如果检测到这一点,程序将立即停止。尽管<gtr=12/>类型在定义上也是所有类型的子类,但<gtr=13/>类型对象不会出现在 Erg 代码中,也不会生成。<gtr=14/>等于<gtr=15/><gtr=16/>是表示省略的对象,来自 Python。也来自 Python。这被用作未实现的标记但 Erg 建议使用<gtr=18/>函数来生成错误。<gtr=19/><gtr=20/>的实例。常用于类型。<gtr=22/>是单元类型,也是实例本身。如果要返回“无意义的值”(如过程的返回值),则使用此选项。
## What is the difference between Never, {}, None, (), NotImplemented, and Ellipsis?
## 为什么有效,而<gtr=24/>是 EffectError
A: `Never` is an "impossible" type. A subroutine that produces a runtime error has `Never` (or a merger type of `Never`) as its return type. The program will stop as soon as it detects this. Although the `Never` type is by definition also a subclass of all types, `Never` type objects never appear in Erg code and are never created. `{}` is equivalent to `Never`.
`Ellipsis` is an object that represents an ellipsis, and comes from Python.
`NotImplemented` is also from Python. It is used as a marker for not implemented, but Erg prefers the `todo` function which produces an error.
`None` is an instance of `NoneType`. It is often used with the `Option` type.
`()` is a unit type and an instance of itself. It is used when you want to return a "meaningless value" such as the return value of a procedure.
A不是标记副作用的产物而是标记可能产生副作用的物体。过程和可变类型<gtr=27/>可能会产生副作用,但例如,如果返回的<gtr=28/>类型为<gtr=29/>,则其本身不会产生副作用。
## Why is `x = p!()` valid but `f() = p!()` causes an EffectError?
## 尝试使用 Python API 时,在 Erg 中,在 Python 中有效的代码出现类型错误。这是什么意思?
`!` is not a marker for the product of a side-effect, but for an object that can cause a side-effect.
Procedure `p!` and mutable type `T!` can cause side effects, but if the return value of `p!()`, for example, is of type `Int`, it itself no longer causes side effects.
Erg 的 API 尽量按照 Python 的 API 规范进行定型,但有些情况无论如何也无法表达。此外,根据 Erg 开发团队的判断,被认为有效但不期望的输入(例如,可以在应输入 int 的地方输入浮点的规范)可能是类型错误。
## When I try to use the Python API, I get a type error in Erg for code that was valid in Python. What does this mean?
A: The Erg API is typed as closely as possible to the Python API specification, but there are some cases that cannot be fully expressed.
Also, input that is valid according to the specification but deemed undesirable (for example, inputting a float when an int should be inputted) may be treated as a type error at the discretion of the Erg development team.

View file

@ -1,13 +1,13 @@
# Python 的改进
# Improvements from Python
## 执行静态分析(静态检查、变量属性检查)
## Perform static analysis (static type checking, variable and property checking)
虽然静态检查的好处不必再强调了,但检查变量属性的存在也是一个非常有效的部分。
The benefit of static type checking cannot be emphasized enough now, but checking for the existence of variables and properties is also a part that comes into play quite a bit.
## 严格处理范围
Python 中的语句没有作用域。因此,在和<gtr=4/>中定义的变量会影响外部。我不能随便命名变量。
## Strict scope handling
In Python, statements do not have scopes.
Therefore, variables defined in a `for` or `if` have outside effects. You cannot name variables casually.
```python
for i in range(10):
@ -16,31 +16,33 @@ for i in range(10):
print(x) # 1
```
在 Erg 中,每一个区块都有一个范围,完全隔离。
In Erg, all blocks have scope and are completely isolated.
## 可变对象和不变对象区别明显
Python 的可变对象和不变对象、堆对象和值对象之间的区别并不明显,因此,我们需要记住一些知识,比如元组是不变的,但列表是可变的……另外,当你想让自己的班级保持不变时,你必须遵循繁琐的步骤。
## Clear distinction between mutable and immutable objects
Python is not clear on the distinction between mutable and immutable / heap and value objects, so you have to keep in mind that tuples are immutable but lists are mutable... You need to keep in mind that tuples are immutable, but lists are mutable... and so on.
Also, if you want to make your own classes immutable, you have to go through a tedious process.
```python
# このコードが過去のPythonでは有効だったと信じられますか?
# Can you believe this code is valid for the past versions of Python?
i = 256
assert i is 256
i = 257
assert i is not 257
```
## trait
## Traits
就像 Java 的界面一样,它可以进行基于合约的编程。
Just like Java's interface, you can do contract-based programming.
Python 也有一个抽象基类,但这种结构与静态定型结合在一起可以发挥最大的作用。
Python also has ABC (Abstract Base Class), but this kind of structure works best with static typing.
## 静态解析依赖关系
## Resolve dependencies statically
防止长时间运行后模块不足而导致错误等导致的游戏体验。
This prevents the annoying experience of running a program for a long time and then running it with an error due to missing modules.
## 内置包管理器
## Built-in package manager
使用标准化的目录结构和构建文件进行可重复的构建。当然,还会生成锁定文件并对其进行版本控制。我们不需要对 anacondapyenvpoetry每个项目进行取舍和组合。
Reproducible builds with a standardized directory structure and build files.
Lock file generation and version control are of course provided.
There is no need to choice or mix anaconda, pyenv, poetry, etc. for each project.

View file

@ -1,25 +1,25 @@
# 指数
# Index
## [API/](./API/index.md)
描述 Erg 的内置或标准库提供的子程序、类型、常量等的规范。
This section describes the specifications of subroutines, types, constants, etc. provided by Erg's built-in or standard libraries.
## [compiler/](./compiler/index.md)
解释了 Erg 编译器(厘米)的设计。
Describes the design of the Erg compiler (Centimetre).
## [dev_guide/](./dev_guide/index.md)
项目的开发方针、贡献方式等进行了说明。
It explains the development policy of the project, how to make contributions, etc.
## [python/](./python/index.md)
解释了开发 Erg 所需的 Python 知识。
The knowledge of Python required to develop Erg is explained.
## [syntax/](./syntax/00_basic.md)
Erg语法解释。
The syntax of Erg is explained.
## [tools/](./tools/index.md)
Erg的外围工具如何使用命令选项等进行了说明。
Explains how to use Erg's peripheral tools and command options.

View file

@ -1,28 +1,25 @@
# Python 到 Erg 迁移的 Tips
# Tips for migrating from Python to Erg
## 要将字符串转换为 int 等
请使用类中的<gtr=5/>方法。它返回类型<gtr=6/>
## I want to convert a string to int etc.
Use the `parse` method of the `Str` class. It returns a `Result` type.
```python
s: str
i: int = int(s)
```
```erg
``` erg
s: Str
res: Result(Int, IntParseError) = s.parse Int
res: Result(Int, IntParseError) = s. parse Int
i: Int = res.unwrap()
f: Result(Float, FloatParseError) = s.parse Float
f: Result(Float, FloatParseError) = s. parse Float
```
也可以使用方法。
You can also use the `try_from` method.
```erg
``` erg
s: Str
i: Int = Int.try_from(s).unwrap()
f: Float = Float.try_from(s).unwrap()
```
```

View file

@ -1,106 +1,114 @@
# Python Bytecode Instructions
Python bytecode 的变量操作系统的指令通过 nameiname index进行访问。这是为了实现 Python 的动态变量访问(可以使用 eval 等以字符串访问。1 命令为 2byte命令、自变量用 little endian 收纳。不取参数的命令也使用 2byte参数部分为 0
Python bytecode variable manipulation commands are accessed through namei (name index). This is to achieve dynamic variable access in Python (which can be accessed as a string using eval, etc.).
One instruction is 2 bytes, and the instruction and arguments are stored in little endian.
Instructions that do not take arguments also use 2 bytes (the argument part is 0).
## STORE_NAME(namei)
```python
globals[namei] = stack.pop()
```
## LOAD_NAME(namei)
```python
stack.push(globals[namei])
```
只能在顶层调用。
Only called at top level.
## LOAD_GLOBAL(namei)
```python
stack.push(globals[namei])
```
这是为了在内部作用域中 Load 在顶层 STORE_NAME 后的内容,但如果在顶层,则与某个作用域代码对象中的 namei 不一定相同(名称相同,而不是 namei
It is for loading STORE_NAME at the top level in the inner scope, but `namei` at the top level is not necessarily the same as namei in the code object of a certain scope (name is the same, not namei)
## LOAD_CONST(namei)
```python
stack.push(consts[namei])
```
从常量表中加载常量。目前Python 3.9CPython 将每个 Lambda 函数都命名为“\”
Load constants in the constant table.
Currently (Python 3.9), in CPython, each lambda function is MAKE_FUNCTION with the name "\<lambda\>"
```console
>>> dis.dis("[1,2,3].map(lambda x: x+1)")
1 0 LOAD_CONST 0 (1)
2 LOAD_CONST 1 (2)
4 LOAD_CONST 2 (3)
6 BUILD_LIST 3
8 LOAD_ATTR 0 (map)
10 LOAD_CONST 3 (<code object <lambda> at 0x7f272897fc90, file "<dis>", line 1>)
12 LOAD_CONST 4 ('<lambda>')
14 MAKE_FUNCTION 0
16 CALL_FUNCTION 1
1 0 LOAD_CONST 0 (1)
2 LOAD_CONST 1 (2)
4 LOAD_CONST 2 (3)
6 BUILD_LIST 3
8 LOAD_ATTR 0 (map)
10 LOAD_CONST 3 (<code object <lambda> at 0x7f272897fc90, file "<dis>", line 1>)
12 LOAD_CONST 4 ('<lambda>')
14 MAKE_FUNCTION 0
16 CALL_FUNCTION 1
18 RETURN_VALUE
```
## STORE_FAST(namei)
fastlocals[namei]=stack.pop可能没有或单个与顶级 STORE_NAME 相对应的参照的变量被认为是这样存储的特意全局空间有自己的指令是为了优化?
fastlocals[namei] = stack.pop()
Possibly corresponds to STORE_NAME at top level
The unreferenced (or single) variable is assumed to be stored by this
Is it for optimization that the global space has its own instructions?
## LOAD_FAST(namei)
stack.pushfastlocals[namei] fastlocals 是 varnames
stack.push(fastlocals[namei])
fastlocals are varnames?
## LOAD_CLOSURE(namei)
```python
cell = freevars[namei]
stack.push(cell)
stack. push(cell)
```
然后,只有在调用 BUILD_TUPLE 的闭包中才会调用 BUILD_TUPLEcellvars 将每个 cell包含引用的容器push 到堆栈中,而 LOAD_DEREF 似乎存储闭包中的引用
Then BUILD_TUPLE is called
It is only called inside the closure, and cellvars are supposed to store references inside the closure.
Unlike LOAD_DEREF, each cell (container filled with references) is pushed to the stack
## STORE_DEREF(namei)
```python
cell = freevars[namei]
cell.set(stack.pop())
```
内部作用域中没有参照的变量被 STORE_FAST但是被参照的变量被 STORE_DEREF 的 Python 中,在这个命令内进行参照计数的增减
Variables without references in inner scopes are STORE_FAST, but referenced variables are STORE_DEREF
In Python, the reference count is incremented and decremented within this instruction
## LOAD_DEREF(namei)
```python
cell = freevars[namei]
stack.push(cell.get())
```
## 名称列表
## name list
### varnames
与 fast_locals 相对应的函数内部变量的名称列表 names 中具有相同名称的变量基本上不相同(新创建的变量,不能从该范围访问外部变量),即没有在范围内定义的外部参照的变量将包含在 varnames 中
Name list of function internal variables corresponding to fast_locals
Even if there are variables with the same name in names, they are basically not the same (newly created and outside variables cannot be accessed from that scope)
i.e. variables without external references defined in scope go into varnames
### names
与 globals 相对应范围内使用的外部常量(仅引用)的名称列表(即使在顶层是普通变量,也会在 names 中)即,范围外定义的常量会在 names 中
Compatible with globals
Name list of external constants (only referenced) used within the scope (at the top level, even ordinary variables are included in names)
i.e. constants defined outside the scope go into names
## free variable
## free variables
对应于 freevars 的闭包捕获的变量。在同一函数实例内进行 static 行为。
Compatible with freevars
Variables captured by the closure. It behaves statically within the same function instance.
## cell variables
cellvars 对应函数内部闭包函数捕获的变量。复制后,原始变量保持不变。
Corresponds to cellvars
Variables captured within a function to an inner closure function. Since a copy is made, the original variable remains as it is.

View file

@ -35,8 +35,8 @@
## PyStringObject
* 如果我使用ascii以外的字符它会变成PyUnicode吗
* "あ", "𠮷”和“α”是PyUnicode不再使用
* If I use a character other than ascii, does it become PyUnicode?
* "あ", "𠮷", and "α" are PyUnicode (no longer used?)
* 0 byte: 0x73 (means 's')
* 1~4 byte: length of string
@ -50,8 +50,8 @@
## PyShortAsciiObject
* 说是 short100 个以上的字也是这个
* 或者说不是 short 没有 asciishort 是数据类型?)
* This is called short, but even if there are more than 100 characters, this will still short
* or rather, there is no ascii that is not short (is short a data type?)
* 0 byte: 0xFA (means 'z')
* 1~4 byte: length of string
@ -59,7 +59,8 @@
## PyInternedObject
** intern 化的对象注册在专用的 map 中,可以用 is 进行比较例如字符串等可以在不考虑长度的常量时间内进行比较
* interned objects are registered in a dedicated map and can be compared with is
* String, for example, can be compared in constant time regardless of its length
* 0 byte: 0x74 (means 't')

View file

@ -1,9 +1,10 @@
# Python 类系统(与 Erg 相比)
# Python class system (compare with Erg)
## 方法
方法即使参照前方也没有关系,这并不是因为使用了特别的技术,而是因为方法的实际存在被动态检查。(在 Erg 中静态检查方法的实际存在。为了参照前方,必须将函数设为常量。)
## Methods
Methods may be forward referenced, but this is not a special technique used.
This is because the existence of a method is dynamically checked.
(In Erg, method existence is checked statically. For forward references, functions must be constants.)
```python
>>> class C:
@ -13,10 +14,10 @@
... def g(self, x): return self.f(x - 1)
```
## 继承,覆盖
被覆盖的某个方法 m 仅仅像变量的再代入那样被覆盖,参照母类 m 的方法在子类中参照被覆盖的 m。
## Inheritance, overriding
Some overridden method m is simply overwritten, like a variable reassignment.
A method that refers to m in the parent class will refer to the overridden m in the child class.
```python
>>> class C:
@ -26,15 +27,14 @@
>>> class D(C):
... def f(self): return 2
...
>>> D().g()
>>>> D().g()
2
```
因此,即使明显错误地被覆盖,在运行时也不会出现错误。
So, even if it is overridden by mistake obviously, it will not be an error until runtime.
```python
>>> class C:
>>>> class C:
... def f(self): return 1
... def g(self): return self.f() + 1
...
@ -43,13 +43,13 @@
...
>>> D().g()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <module
File "<stdin>", line 3, in g
TypeError: can only concatenate str (not "int") to str
```
在 Erg 中静态检查与母类的一致性。在覆盖时,必须赋予装饰器,并且要覆盖的函数类型必须是要覆盖的函数类型的部分类型。
Erg statically checks for consistency with the parent class.
The `Override` decorator must be given when overriding, and the type of the overriding function must be a subtype of the type of the function being overridden.
```erg
>>> C = Class()
@ -60,14 +60,14 @@ TypeError: can only concatenate str (not "int") to str
... .f self = "a"
...
Error[#XX]: File "<stdin>", line 5, in D
.f(self) is already defined in C. To override f, it must be added `Override` decorator and its type must be `Self.() -> Nat` or the subtype of that
.f(self)は既にCで定義されています。オーバーライドするためには`Override`デコレータを付与し、`Self.() -> Nat`型かそのサブタイプである必要があります。
To override f, it must be added `Override` decorator and its type must be `Self.() -> Nat` or the subtype of that
f(self) is already defined in C. To override f, it must be added `Override` decorator and its type must be `Self. To override, it must be given an `Override` decorator and its type must be `Self.() -> Nat` or the subtype of that.f(self).
```
## 类型检查
类型检查大体上只限于函数自变量的类型检查。在 Python 中,大部分的操作都是方法调用。调用时,如果对象所属的类中附有方法的话,就到此为止。
## Type checking
Type checking is generally all about checking the type of function arguments.
In Python, most operations are method calls. If the class to which the object belongs does not have a method attached to it at the time of the call, that's it.
```python
def f(x):
@ -81,7 +81,6 @@ f(c)
f(1) # TypeError
```
```erg
# f: |T, X <: {.m = Self.() -> T}| X -> T
f(x) = x.m()

View file

@ -1,21 +1,23 @@
# 基本信息
# Basics
> 此文档尚未完成。未进行校样文体、正确链接等。此外Erg 的语法在 0.* 版本之间可能会有颠覆性的改变,随之而来的文档更新可能跟不上。请事先谅解。
> 此外,如果你发现本文档中的错误,请从或<gtr=11/>提出更正建议。
> __Warning__: This document is incomplete. It has not been proofread (style, correct links, mistranslation, etc.). Also, Erg's syntax may be change destructively during version 0.*, and the documentation may not have been updated accordingly. Please be aware of this beforehand.
> If you find any errors in this document, please report then to [here form](https://forms.gle/HtLYRfYzWCAaeTGb6) or [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new). We would appreciate your suggestions.
>
> [The Erg book original version (Japanese)](http://mtshiba.me/TheErgBook/)
本文档介绍了 Erg 的基本语法。和<gtr=13/>位于不同的目录中。
This document describes the basic syntax of Erg. The [Standard API](./API/index.md) and [internal documents for Erg contributors](./dev_guide/index.md) are located in another directory.
## Hello, World!
首先按照惯例举办 Hello World 活动吧。
## Hello, World&excl;
First, let's do "Hello World".
```erg
print!("Hello, World!")
```
跟 Python 和同系语言差不多。引人注目的是后面的<gtr=15/>,我会慢慢解释它的含义。此外,在 Erg 中,如果解释不准确,可以省略括号<gtr=16/>。与 Ruby 类似,它可以省略括号,但它不能具有多个解释,也不能在参数为 0 时省略<gtr=17/>,就像 Python 一样。
This is almost identical to Python and other languages in the same family. The most striking feature is the `!`, the meaning of which will be explained later.
In Erg, parentheses `()` can be omitted unless there is some confusion in interpretation.
The omission of parentheses is similar to Ruby, but it is not possible to omit parentheses that can be interpreted in more than one way.
```erg
print! "Hello, World!" # OK
@ -27,43 +29,71 @@ print! f x # OK, interpreted as `print!(f(x))`
print!(f(x, y)) # OK
print! f(x, y) # OK
print! f(x, g y) # OK
print! f x, y # NG, can be taken to mean either `print!(f(x), y)` or `print!(f(x, y))`
print! f x, y # NG, can be taken to mean either `print!(f(x), y)` or `print!(f(x, y))` print!
print!(f x, y) # NG, can be taken to mean either `print!(f(x), y)` or `print!(f(x, y))`
print! f(x, g y, z) # NG, can be taken to mean either `print!(x, g(y), z)` or `print!(x, g(y, z))`
```
## 脚本
## Scripts
Erg 代码称为脚本。可以以文件格式(.er保存和运行脚本。
Erg code is called a script. Scripts can be saved and executed in file format (.er).
## 注释
## REPL/File Execution
及更高版本将作为注释忽略。当你想要解释代码的意图,或者想要暂时禁用代码时,可以使用此选项。
To start REPL, simply type:
```sh
> erg
```
`>` mark is a prompt, just type `erg`.
Then the REPL should start.
```sh
> erg
Starting the REPL server...
Connecting to the REPL server...
Erg interpreter 0.2.4 (tags/?:, 2022/08/17 0:55:12.95) on x86_64/windows
>>>
```
Or you can compile from a file.
```sh
> 'print! "hello, world!"' >> hello.er
> erg hello.er
hello, world!
```
## Comments
The code after `#` is ignored as a comment. Use this to explain the intent of the code or to temporarily disable the code.
```erg
# コメント
## `#`以降は改行されるまで無視されるので、`#`は何個あってもOK
# Comment
# `#` and after are ignored until a new line is inserted
#[
複数行コメント
対応する`]#`のところまでずっとコメントとして扱われます
Multi-line comment
Treated as a comment all the way up to the corresponding `]#`
]#
```
## 表达式,分隔符
脚本是一系列表达式expression。表达式是一个可以计算和评估的东西在 Erg 中几乎所有的东西都是表达式。使用分隔符-换行符或分号-分隔每个表达式。Erg 脚本基本上是从左到右、从上到下进行评估的。
## Expressions, separators
A script is a series of expressions. An expression is something that can be calculated or evaluated, and in Erg almost everything is an expression.
Each expression is separated by a separator - either a new line or a semicolon `;`-.
Erg scripts are basically evaluated from left to right, top to bottom.
```erg
n = 1 # 代入式
f(1, 2) # 関数適用式
1 + 1 # 演算子適用式
n = 1 # assignment expression
f(1, 2) # function-call expression
1 + 1 # operator-call expression
f(1, 2); 1 + 1
```
有一个称为即时块的功能,它使用块中最后计算的表达式作为变量的值,如下所示。这与无参数函数不同,它不使用。请注意,方块只在现场评估一次。
As shown below, there is a syntax called instant block that takes the last expression evaluated in the block as the value of the variable.
This differs from a function with no arguments, which does not add `()`. Note that instant blocks are evaluated only once on the fly.
```erg
i =
@ -72,24 +102,22 @@ i =
assert i == 2
```
这不能通过分号()来实现。
This cannot be accomplished with a semicolon (`;`).
```erg
i = (x = 1; x + 1) # SyntaxError: cannot use `;` in parentheses
```
## 缩进
Erg 使用与 Python 相同的缩进来表示块。触发块开始的运算符(特殊格式)有五种:,<gtr=23/><gtr=24/><gtr=25/><gtr=26/>(其他运算符不是,但<gtr=27/><gtr=28/>也会生成缩进)。它们各自的含义将在后面介绍。
## Indentation
Erg, like Python, uses indentation to represent blocks. There are five operators (special forms) that trigger the start of a block: `=`, `->`, `=>`, `do`, and `do!` (In addition, `:` and `|`, although not operators, also produce indentation). The meanings of each are described later.
```erg
f x, y =
x + y
for! 0..9, i =>
print! i
print!
for! 0..9, i =>
print! i; print! i
@ -101,8 +129,7 @@ ans = match x:
_ -> "unknown"
```
如果一行太长,可以使用在中间换行。
If a line is too long, it can be broken using `\`.
```erg
# this does not means `x + y + z` but means `x; +y; +z`

View file

@ -1,43 +1,40 @@
# Literal
## 基本文字
### 整数文字Int Literal
## Basic Literals
### Int Literal
```erg
0, -0, 1, -1, 2, -2, 3, -3, ...
```
### 有理数文字Ratio Literal
### Ratio Literal
```erg
0.00, -0.0, 0.1, 400.104, ...
```
如果文字中的整数或小数部分为<gtr=21/>,则可以省略<gtr=22/>
If a `Ratio` literal has an integer or decimal part of `0`, you can omit the `0`.
```erg
assert 1.0 == 1.
assert 0.5 == .5
```
> :这个名为<gtr=23/>的函数用于指示<gtr=24/><gtr=25/>相等。
以下文档可能会使用来表示结果相等。
> __Note__: This function `assert` was used to show that `1.0` and `1.` are equal.
Subsequent documents may use `assert` to indicate that the results are equal.
### 字符串文字Str Literal
可以使用 Unicode 表示的任何字符串。与 Python 不同的是,不能进行标定。如果要在字符串中使用<gtr=29/>,请使用<gtr=30/>
### Str Literal
Any Unicode-representable string can be used.
Unlike Python, quotation marks cannot be enclosed in `'`. If you want to use `"` in a string, use `\"`.
```erg
"", "a", "abc", "111", "1# 3f2-3*8$", "こんにちは", "السَّلَامُ عَلَيْكُمْ", ...
```
使用将表达式填充到字符串中。这称为字符串插值。如果要输出<gtr=32/><gtr=33/>本身,请输入<gtr=34/><gtr=35/>
`{}` allows you to embed expressions in strings. This is called string interpolation.
If you want to output `{`, `}` itself, use `\{`, `\}`.
```erg
assert "1 + 1 is 2" == "{1} + {1} is {1+1}"
@ -45,84 +42,74 @@ s = "1+1"
assert "\{1+1}\" == "\{{s}\}"
```
### 指数文字Exponential Literal
这是在学术计算中经常使用的指数表示法的文字。它将成为类型为的实例。用于表示非常大/非常小的数字。与 Python 相同。
### Exponential Literal
This is a literal representing exponential notation often used in academic calculations. It is an instance of type ``Ratio``.
The notation is the same as in Python.
```erg
1e-34, 0.4e-10, 2.455+e5, 245e5, 25E5, ...
```
```erg
assert 1e-10 == 0.0000000001
```
## 文字的组合(复合文字)
## Compound Literals
在文档中,这些文字都有单独的说明,有关详细信息,请参阅。
### 数组文字(./10_array.md
Each of these literals has its own documentation describing them separately, so please refer to that documentation for details.
### [Array Literal](./10_array.md)
```erg
[], [1], [1, 2, 3], ["1", "2",], [1, "1", True, [1]], ...
```
### 字典文字(./11_dict.md
### [Dict Literal](./11_dict.md)
```erg
{:}, {"one": 1}, {"one": 1, "two": 2}, {"1": 1, "2": 2}, {1: "1", 2: True, "three": [1]}, ...
```
### 元组文字(./12_tuple.md
### [Tuple Literal](./12_tuple.md)
```erg
(), (1, 2, 3), (1, "hello", True), ...
```
### 记录文字(./13_record.md
### [Record Literal](./13_record.md)
```erg
{=}, {one = 1}, {one = 1; two = 2}, {.name = "John"; .age = 12}, {.name = Str; .age = Nat}, ...
```
### 集文字(./14_set.md
### [Set Literal](./14_set.md)
```erg
{}, {1}, {1, 2, 3}, {"1", "2", "1"}, {1, "1", True, [1]} ...
```
与文字不同,<gtr=38/>删除重复元素。
As a difference from `Array` literals, duplicate elements are removed in `Set`.
```erg
assert {1, 2, 1} == {1, 2}
```
### 看起来像文字但不像文字的东西
## 真伪对象Boolean Object
### What looks like a literal but isn't
## Boolean Object
```erg
True, False
```
### None 对象
### None Object
```erg
None
```
## 范围对象Range Object
## Range Object
```erg
assert 0..5 == {1, 2, 3, 4, 5}
@ -131,29 +118,26 @@ assert 0..<10 notin 10
assert 0..9 == 0..<10
```
## 浮点对象Float Object
## Float Object
```erg
assert 0.0f64 == 0
assert 0.0f32 == 0.0f64
```
对象乘以<gtr=41/>,即<gtr=40/>的单位对象。
## 复杂对象Complex Object
Float objects are constructed by multiplying a `Ratio` object by `f64`, which is a `Float 64` unit object.
## Complex Object
```erg
1+2im, 0.4-1.2im, 0im, im
```
对象仅通过与<gtr=43/>的运算组合来表示,<gtr=42/>是一个虚单位对象。
A `Complex` object is simply an arithmetic combination of an imaginary unit object, `im`.
## *-less multiplication
Erg 可以省略表示乘法的,除非解释正确。但是,运算符的连接强度设置为大于<gtr=45/>
In Erg, you can omit the `*` to indicate multiplication as long as there is no confusion in interpretation. However, the combined strength of the operators is set stronger than `*`.
```erg
# same as `assert (1*m) / (1*s) == 1*(m/s)`

View file

@ -1,56 +1,55 @@
# 变量
# Variable
变量是代数的一种。Erg 中的代数-有时也称为变量(如果正确)-是指命名对象并使其可从代码中的其他位置使用的功能。
变量定义如下。部分称为变量名(或标识符),<gtr=17/>称为赋值运算符,<gtr=18/>部分称为赋值。
Variables are a type of algebra; algebra in Erg - sometimes simply referred to as variable if there is no confusion - refers to the feature to name objects and make them referable from elsewhere in the code.
A variable is defined as follows.
The `n` part is called the variable name (or identifier), `=` is the assignment operator, and the `1` part is the assigned value.
```erg
n = 1
```
以这种方式定义的随后可用作表示整数对象<gtr=20/>的变量。此系统称为赋值(或绑定)。我们刚才提到了<gtr=21/>是一个对象。我们将在后面讨论对象是什么,但我们现在应该将其赋值到赋值运算符(例如<gtr=22/>)的右侧。
如果要指定变量的类型。类型是指对象所属的集合,这也将在后面介绍。指定为自然数(<gtr=24/>)。
The `n` defined in this way can thereafter be used as a variable to denote the integer object `1`. This system is called assignment (or binding).
We have just said that `1` is an object. We will discuss what an object is later, but for now we will assume that it is something that can be assigned to, i.e., on the right side of the assignment operator (`=`, etc.).
If you want to specify the "type" of a variable, do the following. The type is roughly the set to which an object belongs, as will be explained later.
Here we specify that `n` is a natural number (`Nat`) type.
```erg
n: Nat = 1
```
请注意,与其他语言不同,多重赋值是不可能的。
Note that, unlike other languages, multiple assignments are not allowed.
```erg
# NG
l1 = l2 = [1, 2, 3] # SyntaxError: 多重代入はできません
l1 = l2 = [1, 2, 3] # SyntaxError: multiple assignment not allowed
# OK
l1 = [1, 2, 3]
l2 = l1.clone()
```
也不能对变量进行重新赋值。可以使用的功能,即保持可变状态的功能将在后面讨论。
It is also not possible to reassign to a variable. The syntax that can be used instead, to hold mutable states, are described later.
```erg
i = 1
i = i + 1 # AssignError: cannot assign twice
```
你可以在内部范围内定义具有相同名称的变量,但它们只是放在上面,而不是破坏性地重写值。如果返回到外部范围,则值也将返回。请注意,这与 Python“语句”的作用域不同。这类功能通常称为阴影。但是与其他语言的阴影不同你不能在同一范围内进行阴影。
You can define a variable with the same name in the inner scope, but you are only covering it over, not destructively rewriting its value. If you go back to the outer scope, the value will return as well.
Note that this is a different behavior than the Python "statement" scope.
This kind of functionality is generally referred to as shadowing. However, unlike shadowing in other languages, you cannot shadow in the same scope.
```erg
x = 0
# x = 1 # AssignError: cannot assign twice
if x.is_zero(), do:
x = 1 # 外側のxとは同名の別物
x = 1 # different from outer x with same name
assert x == 1
assert x == 0
```
以下乍一看似乎可行,但还是不行。这不是技术限制,而是设计判断。
The following may seem possible at first glance, but it is still not possible. This is a design decision, not a technical constraint.
```erg
x = 0
@ -60,10 +59,10 @@ if x.is_zero(), do:
assert x == 0
```
## 常数
常数也是代数的一种。如果标识符以大写字母开头,则将其视为常量。它被称为常量,因为它一旦定义就不会改变。部分称为常量名称(或标识符)。其他与变量相同。
## Constants
Constants are also a type of algebra. If you start an identifier with a capital letter, it is treated as a constant. They are called constants because once defined, they do not change.
The `N` part is called the constant name (or identifier). Otherwise, it is the same as a variable.
```erg
N = 0
@ -72,10 +71,11 @@ if True, do:
pass()
```
常量在定义的范围之后变得不变。我也不能阴影。由于该性质,常量可用于模式匹配。后面我们会讨论模式匹配。
Constants are immutable beyond the defined scope. They cannot be shadowed. Because of this property, constants can be used in pattern matching. Pattern matching is explained later.
你可能希望将常量用于不变的值,如数学常量或有关外部资源的信息。除之外的对象通常是全部大写字母(所有字符都是大写的样式)。
For example, constants are used for mathematical constants, information about external resources, and other immutable values.
It is common practice to use all-caps (style in which all letters are capitalized) for identifiers of objects other than [types](./type/01_type_system.md).
```erg
PI = 3.141592653589793
@ -83,7 +83,6 @@ URL = "https://example.com"
CHOICES = ["a", "b", "c"]
```
```erg
PI = 3.141592653589793
match! x:
@ -91,20 +90,19 @@ match! x:
other => print! "other"
```
当为<gtr=28/>时,上面的代码输出<gtr=29/>。如果将<gtr=30/>更改为其他数字,则输出<gtr=31/>
有些常量是不能赋值的。可变对象等等。可变对象是可以更改其内容的对象,如下所述。这是因为常量只能由常量表达式赋值。我们还将在后面讨论常数表达式。
The above code prints `π` when `x` is `3.141592653589793`. If `x` is changed to any other number, it prints `other`.
Some objects cannot be bound as constants. Mutable objects, for example. Mutable objects are objects whose states can be changed, as described in detail later.
This is because of the rule that only constant expressions can be assigned to constants. Constant expressions are also discussed later.
```erg
X = 1 # OK
X = !1 # TypeError: cannot define Int! object as a constant
```
## 删除代数
可以使用函数删除代数。所有依赖于代数(直接引用代数的值)的其他代数都将被删除。
## Delete an Variable
You can delete an variable by using the `Del` function. All other variables that depend on the variable (that is, that refer directly to the value of the variable) are also removed.
```erg
x = 1
@ -119,27 +117,24 @@ Del y, Z
f(2) # NameError: f is not defined (deleted in line 6)
```
但是,只能删除模块中定义的代数。不能删除内置常量,如<gtr=34/>
Note that `Del` can only delete variables defined in the user-defined module. Built-in constants such as `True` cannot be deleted.
```erg
Del True # TypeError: cannot delete built-in constants
Del print! # TypeError: cannot delete built-in variables
```
## Appendix赋值等价性
注意,当时,不一定是<gtr=36/>。例如有<gtr=37/>。这是由 IEEE 754 规定的正式浮点数的规格。
## Appendix: Assignment and Equivalence
Note that `x == a` is not necessarily true when `x = a`. An example is `Float.NaN`. This is the formal specification of floating-point numbers as defined by IEEE 754.
```erg
x = Float.NaN
assert x != Float.NaN
assert x != x
assert x ! = NaN
assert x ! = x
```
其他,也存在原本就没有定义等值关系的对象。
There are other objects for which no equivalence relation is defined in the first place.
```erg
f = x -> x**2 + 2x + 1
@ -151,8 +146,8 @@ D = Class {i: Int}
C == D # TypeError: cannot compare class objects
```
严格地说,并不是将右边值直接代入左边的识别符。函数对象和类对象的情况下,对对象进行赋予变量名的信息等的“修饰”。但是结构型的情况不受此限制。
Strictly speaking, `=` does not assign the right-hand side value directly to the left-hand side identifier.
In the case of function and class objects, "modification" such as giving variable name information to the object is performed. However, this is not the case for structural types.
```erg
f x = x

View file

@ -1,11 +1,12 @@
# 声明
声明是指定要使用的变量类型的语法。可以在代码中的任何地方声明,但不能只声明变量。必须始终初始化。赋值后声明可以检查类型是否与赋值对象匹配。
# Declaration
Declaration is the syntax for specifying the type of variable to be used.
Declarations can be made anywhere in the code, but declarations alone do not refer to the variables. They must be initialized.
After the assignment, the declaration can be checked to ensure that the type is compatible with the object to which it is assigned.
```erg
i: Int
# i: Int = 2可以与赋值同时声明
# Can be declared at the same time as the assignment, like i: Int = 2
i = 2
i: Num
i: Nat
@ -13,26 +14,24 @@ i: -2..2
i: {2}
```
赋值后声明类似于类型检查,但在编译时进行检查。运行时使用<gtr=6/>进行类型检查可以用“可能是 XX”进行检查但编译时使用<gtr=7/>进行类型检查是严格的。如果没有确定是“某某型”,就无法通过检查,就会出现错误。
Declaration after assignment is similar to type checking by `assert`, but has the feature that it is checked at compile time.
Type checking by `assert` at runtime can be checked for "may be type Foo", but type checking by `:` at compile time is strict: if the type is not determined to be "type Foo", it will not pass the check and an error will occur.
```erg
i = (-1..10).sample!()
assert i in Nat # 这可能会通过
i: Int # 这通过了
i: Nat # 这不起作用(因为 -1 不是 Nat 的元素)
i = (-1..10).sample!
assert i in Nat # this may pass
i: Int # this will pass
i: Nat # this will not pass (-1 is not an element of Nat)
```
可以通过两种方式声明函数。
Functions can be declared in 2 different ways.
```erg
f: (x: Int, y: Int) -> Int
f: (Int, Int) -> Int
```
如果显式声明参数名称,则在定义时如果名称不同,将导致类型错误。如果你想给出参数名称的任意性,可以使用第二种方法声明它。在这种情况下,类型检查只显示方法名称及其类型。
If you declare the argument names explicitly, a type error will result if the names are different at definition time. If you want to give the argument names arbitrary names, you can declare them in the second way. In that case, only the method name and its type will be seen by type checking.
```erg
T = Trait {

View file

@ -1,7 +1,6 @@
# 函数
函数是一个块,它接受参数并对其进行处理,然后将其作为返回值返回。定义如下。
# Function
A function is a block that takes an "argument", processes it, and returns it as a "return value". It is defined as follows.
```erg
add x, y = x + y
@ -9,8 +8,10 @@ add x, y = x + y
add(x, y) = x + y
```
在定义函数时指定的参数通常称为伪参数parameter。相反函数调用过程中传递的参数称为实际参数argument。是接受<gtr=31/><gtr=32/>作为假参数,然后返回<gtr=33/>的函数。你可以按如下方式调用(应用)定义的函数。
The names specified after a function name are called parameters.
In contrast, the objects passed to a function are called arguments.
The function `add` is a function that takes `x` and `y` as parameters and returns the sum of them, `x + y`.
The defined function can be called (applied/invoked) as follows.
```erg
add 1, 2
@ -18,30 +19,26 @@ add 1, 2
add(1, 2)
```
## 冒号样式
函数的调用方式如下:,但如果实际参数太多,一行太长,则可以使用<gtr=35/>(冒号)来应用。
## Colon application style
Functions are invoked like `f x, y, ...`, but if there are too many arguments for a single line, they can be applied using `:` (colon).
```erg
f some_long_name_variable_1 + some_long_name_variable_2, some_long_name_variable_3 * some_long_name_variable_4
```
```erg
f some_long_name_variable_1 + some_long_name_variable_2:
some_long_name_variable_3 * some_long_name_variable_4
```
```erg
f:
some_long_name_variable_1 + some_long_name_variable_2
some_long_name_variable_3 * some_long_name_variable_4
```
上面三个代码都是同一个意思。此样式在使用函数时也很有用。
All three codes above mean the same thing. This style is also useful when using `if` functions, for example.
```erg
result = if Bool.sample!():
@ -53,26 +50,24 @@ result = if Bool.sample!():
0
```
在之后,不能写注释以外的代码,必须换行。
After `:`, no code other than comments may be written, and must always be on a new line.
## 关键字参数Keyword Arguments
如果定义了具有大量参数的函数,则可能会导致传递参数的顺序错误。在这种情况下,使用关键字参数进行调用是安全的。
## Keyword Arguments
If a function is defined with a large number of parameters, there is a danger of passing the arguments in the wrong order.
In such cases, it is safe to call the function using keyword arguments.
```erg
f x, y, z, w, v, u: Int = ...
```
上面定义的函数有很多参数,并且排列很难懂。我们不应该做这样的函数,但在使用别人写的代码时可能会碰到这样的代码。因此,我们使用关键字参数。关键字参数的名称优先于顺序,因此即使顺序不正确,也会将值从名称传递到正确的参数。
The functions defined above have many arguments and are arranged in a confusing order. You should not create such a function, but you may encounter such code when using code written by others. Therefore, we use keyword arguments. If you use keyword arguments, the values are passed from the name to the correct argument, even if they are in the wrong order.
```erg
f u: 6, v: 5, w: 4, x: 1, y: 2, z: 3
```
请注意,如果在关键字参数和之后立即换行,将被视为冒号应用样式。
Note that keyword arguments and a new line immediately after the `:` are considered a colon-call style.
```erg
# means `f(x: y)`
@ -83,12 +78,11 @@ f x:
y
```
## 默认参数(Default parameters
## Default parameters
如果一个参数在大多数情况下是固定的,并且你想要省略它,则可以使用默认参数。
缺省参数由or-assign operator指定。如果未指定<gtr=40/>,则将<gtr=41/>赋给<gtr=42/>
Default parameters are used when some parameters are mostly fixed and you want to be able to omit them.
Default parameters are specified by `:=`(walrus operator). If `base` is not specified, assign `math.E` to `base`.
```erg
math_log x: Ratio, base := math.E = ...
@ -97,52 +91,46 @@ assert math_log(100, 10) == 2
assert math_log(100) == math_log(100, math.E)
```
请注意,不指定参数和赋值是有区别的。
Note that there is a distinction between specifying no argument and assigning `None`.
```erg
p! x := 0 = print! x
p! x := 0 = print!
p!(2) # 2
p!() # 0
p!(None) # None
```
也可以与类型和模式一起使用。
Can also be used with type specification and patterns.
```erg
math_log x, base: Ratio := math.E = ...
f [x, y] := [1, 2] = ...
```
但是,在缺省参数中,不能调用以下过程或赋值可变对象。
However, within the default arguments, it is not possible to call the procedures (described later) or assign mutable objects.
```erg
f x := p! 1 = ... # NG
```
此外,不能将刚定义的参数用作传递给缺省参数的值。
Also, the argument just defined cannot be used as the value passed to the default argument.
```erg
f x := 1, y := x = ... # NG
```
## 可变长度参数
函数将参数作为日志输出,可以接收任意数量的参数。
## Variable-length arguments
The `log` function, which outputs a log (record) of its arguments, can take any number of arguments.
```erg
log "Hello", "World", "!" # Hello World !
```
如果要定义这样的函数,请将作为参数。这样,参数就可以作为可变长度数组接收。
To define such a function, add `...` to a parameter. This way, the function receives arguments as a variable-length array.
```erg
f x: ...Int =
f ...x =
for x, i ->
log i
@ -150,8 +138,7 @@ f x: ...Int =
f 1, 2, 3, 4, 5
```
## 多模式函数定义
## Function definition with multiple patterns
```erg
fib n: Nat =
@ -161,8 +148,7 @@ fib n: Nat =
n -> fib(n - 1) + fib(n - 2)
```
如果函数的定义正下方出现,如上面所示,则可以重写如下所示。
Functions like the one above, where `match` appears directly under the definition, can be rewritten as follows.
```erg
fib 0 = 0
@ -170,20 +156,18 @@ fib 1 = 1
fib(n: Nat): Nat = fib(n - 1) + fib(n - 2)
```
请注意,多模式函数定义不是所谓的过载(多重定义)。一个函数始终只有一个类型。在上面的示例中,必须与<gtr=48/><gtr=49/>具有相同的类型。此外,与<gtr=50/>相同,模式匹配从上到下依次进行。
如果存在不同类的混合实例,则必须在最后一个定义中指明函数参数类型为 Or。
Note that a function definition with multiple patterns is not so-called overloading (multiple definition); a function has only a single definition. In the example above, `n` must be of the same type as `0` or `1`. Also, as with `match`, pattern matching is done from top to bottom.
If instances of different classes are mixed, the last definition must specify that the function argument is of type `Or`.
```erg
f "aa" = ...
f 1 = ...
# `f x = ...` is invalid
# `f x = ... ` is invalid
f x: Int or Str = ...
```
它还必须具有包容性,如。
Also, like `match`, it must also be exhaustive.
```erg
fib 0 = 0
@ -191,8 +175,7 @@ fib 1 = 1
# PatternError: pattern of fib's parameter is not exhaustive
```
但是,即使在上述情况下,也可以使用下面的显式指定类型来获得全面性。
However, it can be made exhaustive by explicitly specifying the type using the [refinement type](./type/12_refinement.md) described later.
```erg
fib: 0..1 -> 0..1
@ -201,12 +184,12 @@ fib 1 = 1
# OK
```
## 递归函数
## Recursive functions
递归函数是定义中包含自身的函数。
作为一个简单的例子我们尝试定义函数来计算阶乘。阶乘是“乘以所有小于或等于的正数”的计算。5 的阶乘为。
A recursive function is a function that includes itself in its definition.
As a simple example, let us define a function `factorial` that performs a factorial calculation. Factorial is a computation that "multiplies all positive numbers less than or equal to".
The factorial of 5 is `5*4*3*2*1 == 120`.
```erg
factorial 0 = 1
@ -214,10 +197,13 @@ factorial 1 = 1
factorial(n: Nat): Nat = n * factorial(n - 1)
```
首先从阶乘定义开始0 和 1 的阶乘都是 1. 按顺序计算2 的阶乘为3 的阶乘为4 的阶乘为。如果你仔细观察这里,你会发现一个数字 n 的阶乘是它前面的数字 n-1 的阶乘乘以 n。如果你将其放入代码中则会得到。<gtr=60/>是递归函数,因为<gtr=59/>的定义包含它自己。
注意,如果未指定类型,则会这样推断。
First, from the definition of factorial, the factorial of 0 and 1 are both 1.
In turn, the factorial of 2 is `2*1 == 2`, the factorial of 3 is `3*2*1 == 6`, and the factorial of 4 is `4*3*2*1 == 24`.
If we look closely, we can see that the factorial of a number n is the factorial of the preceding number n-1 multiplied by n.
Putting this into code, we get `n * factorial(n - 1)`.
Since the definition of `factorial` contains itself, `factorial` is a recursive function.
As a reminder, if you do not add a type specification, it is inferred like this.
```erg
factorial: |T <: Sub(Int, T) and Mul(Int, Int) and Eq(Int)| T -> Int
@ -226,19 +212,20 @@ factorial 1 = 1
factorial n = n * factorial(n - 1)
```
但是,即使可以推理,也应该明确指定递归函数的类型。在上面的示例中,像这样的代码是有效的,
However, even if you can reason about it, you should explicitly specify the type of the recursive function. In the example above, a code like ``factorial(-1)`` would work, but
```erg
factorial(-1) == -1 * factorial(-2) == -1 * -2 * factorial(-3) == ...
```
,此计算不会停止。如果不仔细定义值的范围,递归函数可能会陷入无限循环。类型还有助于防止接受不想要的值。
and this computation does not stop. Recursive functions must carefully define the range of values or you may end up in an infinite loop.
So the type specification also helps to avoid accepting unexpected values.
## 编译时函数
如果函数名以大写字母开头,则该函数为编译时函数。所有用户定义的编译时函数的参数都必须是常量,并且必须显式。编译函数能做的事情是有限的。在编译时函数中只能使用常量表达式,即某些运算符(四则运算,比较运算,类型构建运算等)和编译时函数。赋值的参数也必须是常量表达式。相反,计算可以在编译时进行。
## Compile-time functions
A function name begins with an uppercase letter to indicate a compile-time function. User-defined compile-time functions must have all arguments as constants and must specify their types.
Compile-time functions are limited in what they can do. Only constant expressions can be used in compile-time functions, i.e., only some operators (such as quadrature, comparison, and type construction operations) and compile-time functions. Arguments to be passed must also be constant expressions.
In return, the advantage is that the computation can be done at compile time.
```erg
Add(X, Y: Nat): Nat = X + Y
@ -252,18 +239,16 @@ math = import "math"
Sin X = math.sin X # ConstantError: this function is not computable at compile time
```
编译时函数通常用于多相类型定义等。
Compile-time functions are also used in polymorphic type definitions.
```erg
Option T: Type = T or NoneType
Option: Type -> Type
```
## Appendix比较函数
Erg 没有为函数定义。那是因为函数的结构等价性判定算法一般不存在。
## Appendix: Function Comparison
Erg does not define `==` for functions. This is because there is no structural equivalence algorithm for functions in general.
```erg
f = x: Int -> (x + 1)**2
@ -272,18 +257,17 @@ g = x: Int -> x**2 + 2x + 1
assert f == g # TypeError: cannot compare functions
```
<gtr=64/>总是返回相同的结果但这是非常困难的。我们得把代数学灌输给编译器。因此Erg 放弃了整个函数比较,<gtr=65/>也会导致编译错误。这是与 Python 不同的规格,需要注意。
Although `f` and `g` always return the same result, it is extremely difficult to make that determination. We have to teach algebra to the compiler.
So Erg gives up on function comparisons entirely, and `(x -> x) == (x -> x)` also results in a compile error. This is a different specification from Python and should be noted.
```python
# Python, weird example
f = lambda x: x
assert f == f
assert (lambda x: x) != (lambda x: x)
assert (lambda x: x) ! = (lambda x: x)
```
## Appendix2完成
## Appendix2: ()-completion
```erg
f x: Object = ...
@ -299,7 +283,7 @@ f(a, b) # TypeError: f() takes 1 positional argument but 2 were given
f((a, b)) # OK
```
函数类型实际上是<gtr=67/>的语法糖。
The function type `T -> U` is actually the syntax sugar of `(T,) -> U`.
<p align='center'>
<a href='./03_declaration.md'>Previous</a> | <a href='./05_builtin_funcs.md'>Next</a>

View file

@ -1,9 +1,8 @@
# 内置函数
# Built-in functions
## if
是一个函数,它可以根据条件改变操作。
`if` is a function that changes processing depending on a condition.
```erg
result: Option Int = if! Bool.sample!(), do:
@ -12,8 +11,8 @@ result: Option Int = if! Bool.sample!(), do:
print! result # None (or 1)
```
随机返回集合的值。如果返回值为 true则执行<gtr=7/>。还可以指定当条件为假时如何处理。第二个 do 块称为 else 块。
`.sample!()` returns a random set of values. If the return value is true, `print! "True"` is executed.
You can also specify what to do if the condition is false; the second do block is called the else block.
```erg
result: Nat = if Bool.sample!():
@ -26,8 +25,7 @@ result: Nat = if Bool.sample!():
print! result # 1 (or 0)
```
如果只执行一行操作,则可以省略缩进。
If the process is a single line, you can omit indentation.
```erg
result = if Bool.sample!():
@ -37,8 +35,7 @@ result = if Bool.sample!():
## for
你可以使用来编写重复的操作。
You can use `for` to write a repeating process.
```erg
match_s(ss: Iterator(Str), pat: Pattern): Option Str =

View file

@ -1,13 +1,13 @@
# 运算符
# operator
运算符(操作符)是表示运算的符号。运算符(操作数)位于运算符的右侧(左),在 Erg 中它只是一个对象。
Operators are symbols that represent operations. Operands are things to the (left) right of an operator.
运算符是一种函数,因此它本身也可以绑定到一级对象中的变量。绑定必须用包围。对于<gtr=4/>(和<gtr=5/>),必须指定<gtr=6/>(二元运算)/<gtr=7/>(一元运算)以实现唯一化,因为同时存在一元运算符和二元运算符。
Operators are a kind of function, and thus are themselves first-class objects that can be bound to variables. When binding, it is necessary to enclose it with ``.
For `+` (and `-`), there are both unary and binary operators, so `_+_`(binary operation)/`+_`(unary operation ) must be specified.
```erg
``` erg
add = `+` # SyntaxError: specify `_+_` or `+_`
add = `_+_`
add=`_+_`
assert f(1, 2) == 3
assert f("a", "b") == "ab"
@ -15,10 +15,9 @@ g = `*` # OK, this is binary only
assert g(1, 2) == 2
```
但是,请注意,某些称为特殊格式的运算符不能被绑定。
Some fundamental operators, called special forms, cannot be bound.
```erg
``` erg
def = `=` # SyntaxError: cannot bind `=` operator, this is a special form
# NG: def x, 1
function = `->` # SyntaxError: cannot bind `->` operator, this is a special form

View file

@ -1,36 +1,34 @@
# 副作用和过程
到目前为止,我一直没有解释中<gtr=11/>的含义,现在我终于明白了它的含义。这个!直截了当地表示此对象是具有“副作用”的“过程”。过程对函数产生了一种称为“副作用”的效果。
# Side effects and procedures
We have been neglecting to explain the meaning of the `!`, but now its meaning will finally be revealed. This `!` indicates that this object is a "procedure" with a "side-effect". A procedure is a function with a side-effect.
```erg
f x = print! x # EffectError: functions cannot be assigned objects with side effects
# hint: change the name to 'f!'
```
上面的代码是编译错误。因为你在函数中使用过程。在这种情况下,必须将其定义为过程。
The above code will result in a compile error. This is because you are using a procedure in a function. In such a case, you must define it as a procedure.
```erg
p! x = print! x
```
<gtr=13/>...是代表过程的典型变量名称。以这种方式定义的过程也不能在函数中使用,因此副作用是完全隔离的。
`p!`, `q!`, ... are typical variable names for procedures.
Procedures defined in this way also cannot be used within a function, so side-effects are completely isolated.
## 方法
每个函数和过程都有一个方法。函数方法仅保留的不变引用,过程方法保留<gtr=15/>的可变引用。<gtr=16/>是一个特殊参数,在方法上下文中是指调用的对象本身。引用的<gtr=17/>不能指定给任何其他变量。
## Methods
Functions and procedures each can be methods. Functional methods can only take immutable references to `self`, while procedural methods can take mutable references to `self`.
The `self` is a special parameter, which in the context of a method refers to the calling object itself. The reference `self` cannot be assigned to any other variable.
```erg
C.
C!.
method ref self =
x = self # OwnershipError: cannot move out 'self'
x
```
该方法还可以剥夺的所有权。该方法的定义不包括<gtr=19/><gtr=20/>
Procedural methods can also take [ownership](./18_ownership.md) of `self`. Remove `ref` or `ref!` from the method definition.
```erg
n = 1
@ -38,39 +36,39 @@ s = n.into(Str) # '1'
n # ValueError: n was moved by .into (line 2)
```
始终只能有一个过程方法具有可变引用。此外,当可变参照被取走时,将无法从原始对象获取参照。从这个意义上说,会对<gtr=22/>产生副作用。
但是,请注意,可以从可变参照生成(不变/可变)参照。这允许你在过程方法中递归或。
Only one procedural methods can have a mutable reference at any given time. In addition, while a mutable reference is taken, no more mutable reference can be taken from the original object. In this sense, `ref!` causes a side-effect on `self`.
Note, however, that it is possible to create (immutable/mutable) references from mutable references. This allows recursion and `print!` of `self` in procedural methods.
```erg
T -> T # OK (move)
T -> Ref T # OK
T -> Ref T # OK (move)
T => Ref! T # OK (only once)
Ref T -> T # NG
Ref T -> Ref T # OK
Ref T => Ref! T # NG
Ref! T -> T # NG
Ref! T -> Ref T # OK
Ref! T => Ref! T # OK
Ref T => Ref!
T -> Ref T # NG
T -> Ref T # OK
T => Ref!
```
## Appendix:严格定义副作用
## Appendix: Strict definition of side-effects
代码有没有副作用的规则并不是马上就能理解的。在理解之前,建议先将其定义为函数,然后在出现错误时将其定义为过程。但是,对于那些想要掌握语言严格规范的人来说,下面我们会更详细地介绍副作用。
The rules for whether a code has a side-effect or not are not immediately understandable.
Until you can understand them, we recommend that you leave it to the compiler to define them as functions for the time being, and if an error occurs, add `!` to treat them as procedures.
However, for those who want to understand the exact specifications of the language, the following is a more detailed explanation of side-effects.
首先,请注意,返回值的等价性与 Erg 中的副作用无关。对于任何,都有一个过程(例如,总是返回<gtr=27/>),也有一个函数是<gtr=28/>
前一个示例是,后一个示例是以下函数。
First, it must be stated that the equivalence of return values is irrelevant with respect to side effects in Erg.
There are procedures that for any given `x` will result in `p!(x) == p!(x)` (e.g. always return `None`), and there are functions that will result in `f(x) ! = f(x)`.
An example of the former is `print!`, and an example of the latter is the following function.
```erg
nan _ = Float.NaN
assert nan(1) != nan(1)
assert nan(1) ! = nan(1)
```
也有一些对象无法进行等价判定,例如类或函数。
There are also objects, such as classes, for which equivalence determination itself is not possible.
```erg
T = Structural {i = Int}
@ -82,14 +80,13 @@ D = Class {i = Int}
assert C == D # TypeError: cannot compare classes
```
回到正题上来。“副作用”在 Erg 中的确切定义是,
Back to the point: the precise definition of "side-effect" in Erg is
* 访问外部可变信息
* Accessing mutable external information.
中选择所需的墙类型。外部通常是指外部范围。“外部”不包括 Erg 无法接触的计算机资源或运行前/运行后信息。“访问”不仅包括写入,还包括读取。
以过程为例。<gtr=31/>看似没有重写任何变量。但是,如果这是一个函数,那么外部变量可以用这样的代码重写。
"External" generally refers to the outer scope; computer resources that Erg cannot touch and pre-/post-execution information are not included in "external". "Access" includes reading as well as writing.
As an example, consider the `print!` procedure. At first glance, `print!` does not seem to rewrite any variables. But if it were a function, it could rewrite outer variables, for example, with code like this:
```erg
camera = import "some_camera_module"
@ -97,17 +94,18 @@ ocr = import "some_ocr_module"
n = 0
_ =
f x = print x # 仮にprintを関数として使えたとします
f x = print x # Suppose we could use print as a function
f(3.141592)
cam = camera.new() # カメラはPCのディスプレイを向いています
cam = camera.new() # camera faces PC display
image = cam.shot!()
n = ocr.read_num(image) # n = 3.141592
```
模块是为相机产品提供 API 的外部库,<gtr=33/>是 OCR光学字符识别的库。直接副作用是由<gtr=34/>引起的,但显然,这些信息是从<gtr=35/>泄露的。因此,<gtr=36/>在性质上不能是函数。
然而,当你在函数中临时检查值时,你可能不希望将附加到相关函数中。在这种情况下,可以使用函数<gtr=38/><gtr=39/>在执行整个代码后显示值。这不会传播副作用。
Think of the `camera` module as an external library providing an API for a certain camera product, and `ocr` as a library for OCR (optical character recognition).
The direct side-effect is caused by `cam.shot!()`, but obviously that information is leaked from `f`. Therefore, `print!` cannot be a function by nature.
Nevertheless, there may be cases where you want to temporarily check a value in a function and do not want to add `!` in the related function just for that purpose. In such cases, the `log` function can be used.
`log` prints the value after the entire code has been executed. In this way, side-effects are not propagated.
```erg
log "this will be printed after execution"
@ -116,7 +114,7 @@ print! "this will be printed immediately"
# this will be printed after execution
```
换句话说,如果程序没有反馈,即任何外部对象都不能使用该信息,则信息的“泄露”本身可能是允许的。不被“传播”就行了。
If there is no feedback to the program, or in other words, if no external object can use the internal information, then the "leakage" of the information may be allowed. It is only necessary that the information not be "propagated".
<p align='center'>
<a href='./06_operator.md'>Previous</a> | <a href='./08_procedure.md'>Next</a>

View file

@ -1,7 +1,7 @@
# 过程
处理可变对象时需要过程,但如果变量对象是参数,则不一定是过程。
# Procedures
Procedures are necessary when dealing with mutable objects, but having a mutable object as an argument does not necessarily make it a procedure.
Here is a function takes a mutable object (not procedure).
```erg
peek_str s: Str! = log s

View file

@ -1,9 +1,10 @@
# 内置过程
# Built-in procedure
## id!
返回对象的唯一标识号。在纯 Erg 语义中,结构相同的对象之间没有差异,但实际上,对象在内存中的位置是不同的。返回表示此位置的数字。
Returns the unique identification number of the object.
Although in pure Erg semantics no difference can be found between objects with the same structure, in practice objects have different locations in memory.
`id!` returns a number representing this position.
```erg
```

View file

@ -1,12 +1,12 @@
# 排列
数组是最基本的。集合是可以在内部包含多个对象的对象。
# Array
Arrays are the most basic __collection (aggregate)__.
A collection is an object that can hold multiple objects inside it.
```erg
a = [1, 2, 3]
a: [Int; 3] # 型指定: セミコロンの後の数字は要素数
# 要素数がわからない場合は省略可能
a: [Int; 3] # Type specification: number after semicolon is the number of elements
# Can be omitted if the number of elements is not known
a: [Int]
mut_a = [!1, !2, !3]
@ -14,41 +14,37 @@ mut_a[0].inc!()
assert mut_a == [2, 2, 3]
```
通常,数组不能包含不同类型的对象。
As a rule, arrays cannot contain objects of different types.
```erg
```erg.
[1, "a"] # TypeError: 1st element is Int, but 2nd element is Str
```
但是,这种显式类型可以避免限制。
However, you can bypass the restriction by explicitly specifying the type like this.
```erg
[1, "a"]: [Int or Str]
[1, "a"]: [Int or Str].
```
## 切片
数组还可以同时检索多个值。我们管这个叫切片。
## Slice
An array can also have multiple values taken out at once. This is called slicing.
```erg
l = [1, 2, 3, 4]
# Pythonのl[1:3]に相当
assert l[1..<3] == [2, 3]
# Same as l[1:3] in Python
assert l[1.. <3] == [2, 3]
assert l[1..2] == [2, 3]
# l[1]と同じ
# Same as l[1]
assert l[1..1] == [2]
# Pythonのl[::2]に相当
# Same as l[::2] in Python
assert l[..].step(2) == [2, 4]
```
切片获得的对象是数组的(不可变)引用。
The object obtained by slicing is an (immutable) copy to an array.
```erg
print! Typeof l[1..2] # Ref [Int; 4]
print! Typeof l[1..2] # [Int; 4]
```
<p align='center'>

View file

@ -1,7 +1,7 @@
# 元
元组类似于数组,但可以包含不同类型的对象。这样的收藏称为非等质收藏。与此相对,等质集合包括数组和集合。
# Tuple
Tuples are similar to arrays, but can hold objects of different types.
Such a collection is called an unequal collection. In contrast, homogeneous collections include arrays, sets, etc.
```erg
t = (1, True, "a")
@ -9,8 +9,8 @@ t = (1, True, "a")
assert(i == 1 and b == True and s == "a")
```
元组可以以<gtr=14/>的形式检索第 n 个元素。请注意,与 Python 不同,它不是。这是因为元组元素的访问更接近于属性,而不是方法(数组中的<gtr=16/>是方法)(编译时检查元素是否存在,类型可以根据 n 而变化)。
The tuple `t` can retrieve the nth element in the form `t.n`; note that unlike Python, it is not `t[n]`.
This is because accessing tuple elements is more like an attribute (the existence of the element is checked at compile time, and the type can change depending on `n`) than a method (an array's `[]` is a method).
```erg
assert t.0 == 1
@ -18,97 +18,89 @@ assert t.1 == True
assert t.2 == "a"
```
不嵌套时,括号是可选的。
Parentheses `()` are optional when not nested.
```erg
t = 1, True, "a"
i, b, s = t
```
元组可以包含不同类型的对象,但不能包含数组之类的小版本。
Tuples can hold objects of different types, so they cannot be iterated like arrays.
```erg
t: ({1}, {2}, {3}) = (1, 2, 3)
(1, 2, 3).iter().map(x -> x + 1) # TypeError: type ({1}, {2}, {3}) has no method `.iter()`
# すべて同じ型の場合配列と同じように`(T; n)`で表せるが、これでもイテレーションは出来ない
# If all types are the same, they can be represented by `(T; n)` like arrays, but this still does not allow iteration
t: (Int; 3) = (1, 2, 3)
assert (Int; 3) == (Int, Int, Int)
```
但是非等质集合如元组可以通过上传、Intersection 等转换为等质集合(如数组)。这叫做等质化。
However, nonhomogeneous collections (such as tuples) can be converted to homogeneous collections (such as arrays) by upcasting, intersecting, and so on.
This is called equalization.
```erg
(Int, Bool, Str) can be [T; 3] | T :> Int, T :> Bool, T :> Str
(Int, Bool, Str) can be [T; 3] where T :> Int, T :> Bool, T :> Str
```
```erg
t: (Int, Bool, Str) = (1, True, "a") # non-homogenous
a: [Int or Bool or Str; 3] = [1, True, "a"] # homogenous
_a: [Show; 3] = [1, True, "a"] # homogenous
_a.iter().map(x -> log x) # OK
t.try_into([Show; 3])?.iter().map(x -> log x) # OK
t.try_into([Show; 3])? .iter().map(x -> log x) # OK
```
## 单位
具有 0 个元素的元组称为单元。单位是一个值,但也指其类型本身。
## Unit
A tuple with zero elements is called a __unit__. A unit is a value, but also refers to its own type.
```erg
unit = ()
(): ()
```
单元是所有元素 0 元组的超类。
Unit is a superclass of all element 0 tuples.
```erg
() > (Int; 0)
() > (Str; 0)
```
此对象的用途包括参数、没有返回值的过程等。Erg 子例程必须具有参数和返回值。但是,在某些情况下,例如在过程中,可能会产生副作用,但没有有意义的参数返回值。在这种情况下,单位作为“没有意义的,形式上的值”来使用。
The use of this object is for procedures with no arguments and no return value, etc. Erg subroutines must have arguments and a return value. However, in some cases, such as a procedure, there may be no meaningful arguments or return value, only side effects. In such cases, we use units as "meaningless, formal values.
```erg
# ↓ 実はこの括弧はユニット
p!() =
# `print!`は意味のある値を返さない
# ↓ Actually, this parenthesis is a unit
p!() =.
# `print!` does not return a meaningful value
print! "Hello, world!"
p!: () => ()
```
但是Python 在这种情况下更倾向于使用而不是单位。在 Erg 中,如果一开始就确定不返回有意义的值(如过程),则返回<gtr=19/>;如果操作失败,可能一无所获(如元素检索),则返回<gtr=20/>
However, Python tends to use `None` instead of units in such cases.
In Erg, you should use `()` when you are sure from the beginning that the operation will not return a meaningful value, such as in a procedure, and return `None` when there is a possibility that the operation will fail and you will get nothing, such as when retrieving an element.
## 参数和元组
实际上Erg 的所有对象都是一个参数,一个返回值。具有 N 个参数的子程序仅接受“一个具有 N 个元素的元组”作为参数。
## Arguments and Tuple
Actually, all of Erg's `Callable` objects are one argument and one return value; a subroutine that takes N arguments was just receiving "one tuple with N elements" as an argument.
```erg
# f x = ...は暗黙にf(x) = ...とみなされる
# f x = ... is implicitly assumed to be f(x) = ... is considered to be
f x = x
assert f(1) == 1
f(1, 2, 3) # ArgumentError: f takes 1 positional argument but 3 were given
# 可変個の引数を受け取る
g x: Int, ...y: Int = y
# ArgumentError: f takes 1 positional argument but 3 were given
g x: Int, . . y: Int = y
assert (2, 3) == g 1, 2, 3
```
这将解释函数的类型。
This also explains the function type.
```erg
assert f in T: {(T,) -> T | T}
assert g in {(Int, ...(Int; N)) -> (Int; N) | N: Nat}
assert g in {(Int, ... (Int; N)) -> (Int; N) | N: Nat}
```
准确地说,函数的输入不是元组,而是具有默认属性的命名元组。这是一个特殊的元组,只能作为函数的参数使用,可以像记录一样命名并具有缺省值。
To be precise, the function's input is not a tuple but a "Named tuple with default attributes". This is a special tuple that can only be used in function arguments, can be named like a record, and can have a default value.
```erg
f(x: Int, y=0) = x + y

View file

@ -1,40 +1,37 @@
# Dict
Dict 是一个包含键值对的集合。
Dict is a collection of key/value pairs.
```erg
ids = {"Alice": 145, "Bob": 214, "Charlie": 301}
assert ids["Alice"] == 145
```
如果密钥为 Hash则该密钥可以不是字符串。
The key does not have to be a string if it is a `Hash` object.
```erg
# rangeオブジェクトをキーにするのは非推奨(スライスと混同される)
# deprecated to use a range object as a key (confused with slice)
r = {1..3: "1~3", 4..6: "4~6", 7..9: "7~9"}
assert r[1..3] == "1~3"
l = {[]: "empty", [1]: "1"}
assert l[[]] == "empty"
```
顺序对迪奇并不重要。也不能有重复的元素。在这一点上Dict 与相似。Dict 也可以说是一个有价值的 Set。
Order does not matter for Dict. It also cannot have duplicate elements. In this respect, Dict is similar to Set.
You could say that a Dict is a Set with values.
```erg
{"Alice": 145, "Bob": 214, "Charlie": 301} == {"Alice": 145, "Charlie": 301, "Bob": 214}
```
从 Dict 文字生成 Dict 时,将检查是否存在重复的键。如果存在重复项,则会导致编译错误。
When generating a dict from a dict literal, it is checked for duplicate keys.
Any duplicates will result in a compile error.
```erg
{"Alice": 145, "Alice": 1} # KeyError: Duplicate key "Alice"
```
使用生成空 Dict。请注意表示空数组。
Empty Dict is created with `{:}`. Note that `{}` denotes an empty set.
```erg
mut_dict = !{:}
@ -45,25 +42,24 @@ assert mut_dict["Alice"] == 145
## Heterogeneous Dict
键值的类型可以不是单一的,这样的字典称为。
There need not be a single key/value type. Such a dictionary is called a __heterogenous dict_.
```erg
d: {Str: Int, Int: Str} = {”a”: 1, 1: “a”}
assert d[”a”] == 1
assert d[1] == “a”
d: {Str: Int, Int: Str} = {"a": 1, 1: "a"}
assert d["a"] == 1
assert d[1] == "a"
```
但是,不能将相同类型的值应用于不同类型的键,也不能将不同类型的值应用于不同类型的键。在这些情况下,请改用 Or 类型Union
However, it is not possible to assign values of the same type to keys of different types, or values of different types to keys of the same type.
In such cases, use the type Or instead.
```erg
invalid1 = {1: “a”, “a”: “b”}
invalid2 = {1: “a”, 2: 2}
invalid1 = {1: "a", "a": "b"}
invalid2 = {1: "a", 2: 2}
# Ergの型推論はOr型を推論しないので、型指定が必要
valid1: {Int or Str: Str} = {1: “a”, “a”: “b”}
valid2: {Int: Int or Str} = {1: “a”, 2: 2}
# Erg type inference does not infer Or type, so type specification is required
valid1: {Int or Str: Str} = {1: "a", "a": "b"}
valid2: {Int: Int or Str} = {1: "a", 2: 2}
```
<p align='center'>

View file

@ -1,7 +1,7 @@
# 记录
记录是一个集合,它具有通过键访问的 Dict 和在编译时检查访问的元组的性质。如果你使用过 JavaScript请将其视为对象文字符号更高级
# Record
A record is a collection that combines the properties of a Dict accessed by key and a tuple whose access is inspected at compile time.
If you know JavaScript, think of it as a (more enhanced) kind of object literal notation.
```erg
john = {.name = "John"; .age = 21}
@ -12,33 +12,34 @@ assert john in {.name = Str; .age = Nat}
john["name"] # Error: john is not subscribable
```
<gtr=15/>部分称为属性,<gtr=16/><gtr=17/>部分称为属性值。
它与 JavaScript 对象文字的区别在于不能以字符串形式访问。也就是说,属性不仅仅是字符串。这可能是因为它在编译时决定对值的访问,也可能是因为字典和记录是不同的。也就是说,是 Dict<gtr=19/>是记录。那么,词典和记录该如何区分使用呢?通常建议使用记录。记录具有以下优点:编译时检查元素是否存在,并且可以指定<gtr=21/>。可见性规范相当于 public/private 规范,例如在 Java 语言中。有关详细信息,请参见<gtr=20/>
The `.name` and `.age` parts are called attributes, and the `"John"` and `21` parts are called attribute values.
The difference from JavaScript object literals is that they are not accessible as strings. That is, attributes are not just strings.
This is because access to the value is determined at compile-time, and because dictionaries and records are different things. In other words, `{"name": "John"}` is a Dict and `{name = "John"}` is a record.
So how should we use dictionaries and records?
In general, we recommend using records. Records have the advantages of being checked at compile-time for the existence of elements and of being able to specify __visibility_.
Specifying visibility is equivalent to specifying public/private in Java and other languages. For details, see [visibility](./15_visibility.md) for details.
```erg
a = {x = 1; .y = x + 1}
a.x # AttributeError: x is private
# Hint: declare as `.x`
# Hint: declare as `.x`.
assert a.y == 2
```
对于熟悉 JavaScript 的人来说,上面的例子可能很奇怪,但如果简单地声明,则外部无法访问,如果加上<gtr=23/>,则可以通过<gtr=24/>访问。
还可以显式指定属性的类型。
The above example may seem strange to someone familiar with JavaScript, but simply declaring `x` makes it inaccessible from the outside. `. `. `.
You can also explicitly specify the type of an attribute.
```erg
anonymous = {
.name: Option! Str = !None
.name: Option! Str = !
.age = 20
}
anonymous.name.set! "John"
```
记录也可以有方法。
A record can also have the method.
```erg
o = {
@ -51,28 +52,27 @@ o.inc!()
assert o.i == 1
```
关于记录有一个值得注意的语法。当记录的所有属性值都是类(结构类型不允许)时,记录本身将其属性视为请求属性。这种类型称为记录类型。有关详细信息,请参阅记录部分。
There is a notable syntax with respect to records. When all the attribute values of a record are classes (not structural types), the record itself behaves as a type with its own attributes as required attributes.
Such a type is called a record type. See the section [Record] for more details.
```erg
# レコード
# record
john = {.name = "John"}
# レコード型
# record type
john: {.name = Str}
Named = {.name = Str}
john: Named
greet! n: Named =
print! "Hello, I am {n.name}"
greet! john # "Hello, I am John"
john # "Hello, I am John" print!
print! Named.name # Str
Named.name # Str
```
## 分解记录
可以按如下方式分解记录。
## Deconstructing a record
Records can be deconstructed as follows.
```erg
record = {x = 1; y = 2}
@ -88,8 +88,8 @@ match point:
{x = x; y = y; z = z} -> "({x}, {y}, {z})"
```
此外,如果记录具有与属性同名的变量,则可以将或<gtr=26/>省略为<gtr=27/>,将<gtr=28/><gtr=29/>省略为<gtr=30/>。但是,如果只有一个属性,则必须使用<gtr=31/>将其与集合区分开来。
`x = ...` can also be abbreviated to `x` when there is a variable with the same name as the attribute, for example, `x = x` or `x = .x` to `x`, and `.x = .x` or `.x = x` to `.x`.
However, when there is only one attribute, it must be followed by `;` to distinguish it from a set.
```erg
x = 1
@ -106,8 +106,7 @@ tuple = {x}
assert tuple.1 == 1
```
此语法可用于分解记录并将其赋给变量。
This syntax can be used to deconstructed a record and assign it to a variable.
```erg
# same as `{x = x; y = y} = xy`
@ -120,10 +119,9 @@ assert a == 1
assert b == 2
```
## 空记录
空记录由表示。与 Unit 一样,空记录也是其类本身。
## Empty Record
An empty record is represented by `{=}`. An empty record is also its own class, like Unit.
```erg
empty_record = {=}
@ -134,23 +132,26 @@ empty_record: Structural {=}
{x = 3; y = 5}: Structural {=}
```
空记录不同于空 Dict或空集<gtr=34/>。尤其要注意它与<gtr=35/>的含义正好相反(在 Python 中,<gtr=36/>是一个空字典,而在 Erg 中,它是<gtr=37/>)。作为枚举类型,<gtr=38/>是空类型,不包含任何元素。类型是对其进行的类化。相反,记录类中的<gtr=40/>没有请求实例属性,因此所有对象都是它的元素。是此别名。<gtr=42/>(修补程序)具有非常基本的提供方法,如<gtr=43/>
An empty record is different from an empty Dict `{:}` or empty set `{}`. In particular, note that it is the opposite of `{}` in meaning (in Python, `{}` is an empty dictionary, while in Erg it is `!{:}` in Erg).
As an enumerated type, `{}` is an empty type that contains nothing in its elements. The `Never` type is a classification of this type.
Conversely, the record class `{=}` has no required instance attribute, so all objects are elements of it. An `Object` is an alias of this.
An `Object` (a patch of `Object`) is an element of `. __sizeof__` and other very basic provided methods.
```erg
AnyPatch = Patch Structural {=}
.__sizeof__ self = ...
. __sizeof__ self = ...
.clone self = ...
...
Never = Class {}
```
请注意,没有其他类型和类在结构上与,<gtr=45/>类型等效,如果用户定义类型时在右边指定<gtr=46/><gtr=47/>,则会出错。这可以防止将<gtr=48/>转换为<gtr=49/>的错误。此外,如果定义组合结果为<gtr=50/>的类型(例如<gtr=51/>),则会发出警告,将其简单地定义为<gtr=52/>
Note that no other type or class can be structurally equivalent to the `{}`, `Never` type, and it is an error if the user defines a type with `{}`, `Class {}` on the right side.
This means that, for example, `1..10 or -10. -1`, but `1..10 and -10... -1`. `-1` when it should be `1..10 or -10...-1`, for example.
Also, if you define a type (such as `Int and Str`) that results in a composition `Object`, you will be warned to simply set it to `Object`.
## 即时块
Erg 还有一个语法叫即时块,它只是返回最后评估的值。不能保留属性。
## Instant Block
Erg has another syntax, instant block, which simply returns the last value evaluated. Attributes cannot be retained.
```erg
x =
@ -163,10 +164,10 @@ y =
.x = 1 # SyntaxError: cannot define an attribute in an entity block
```
## 数据类
如果尝试单独实现方法,则必须直接在实例中定义原始记录(由记录文本生成的记录)。这效率很低,而且随着属性数量的增加,错误显示等很难看到,也很难使用。
## Data Class
A bare record (a record generated by a record literal) must be defined directly in the instance if you try to implement a method on its own.
This is inefficient, and as the number of attributes increases, error messages and the like become difficult to see and use.
```erg
john = {
@ -176,11 +177,11 @@ john = {
.inc_age! ref! self = self::age.update! x -> x + 1
}
john + 1
# TypeError: + is not implemented for {name = Str; age = Int; .greet! = Ref(Self).() => None; inc_age! = Ref!(Self).() => None}, Int
# TypeError: + is not implemented for {name = Str; age = Int; .greet! = Ref(Self). () => None; inc_age! = Ref! () => None}, Int
```
因此,在这种情况下,我们将继承记录类。此类类称为数据类。我们将在部分详细讨论这一点。
So, in such a case, you can inherit a record class. Such a class is called a data class.
This is described in [class](./type/04_class.md).
```erg
Person = Inherit {name = Str; age = Nat}
@ -194,5 +195,5 @@ john + 1
```
<p align='center'>
<a href='./12_dict.md'>Previous</a> | <a href='./14_set.md'>Next</a>
<a href='./12_tuple.md'>Previous</a> | <a href='./14_set.md'>Next</a>
</p>

View file

@ -1,18 +1,16 @@
#
# Set
集代表一个集合,在数据结构上是重复的、没有顺序的数组。
A set represents a collection, which is structurally a duplicate, unordered array.
```erg
``` erg
assert Set.from([1, 2, 3, 2, 1]) == {1, 2, 3}
assert {1, 2} == {1, 1, 2} # 重複は自動で削除される
assert {1, 2} == {1, 1, 2} # duplicates are automatically removed
assert {1, 2} == {2, 1}
```
集合可以进行集合运算。
Sets can perform set operations.
```erg
``` erg
assert 1 in {1, 2, 3}
assert not 1 in {}
assert {1} or {2} == {1, 2}
@ -20,31 +18,29 @@ assert {1, 2} and {2, 3} == {2}
assert {1, 2} not {2} == {1}
```
布景是一个等质的收藏。要使不同类中的对象共存,必须使它们相等。
A set is a homogeneous collection. In order for objects of different classes to coexist, they must be homogenized.
```erg
``` erg
s: {Int or Str} = {"a", 1, "b", -1}
```
## 设置为类型
## Sets as types
套也可以当作一种类型。这些类型称为。
Sets can also be treated as types. Such types are called __Enum types__.
```erg
``` erg
i: {1, 2, 3} = 1
assert i in {1, 2, 3}
```
集的元素将变为类型元素。需要注意的是,布景本身是不一样的。
Elements of the set are directly elements of the type.
Note that the sets themselves are different.
```erg
``` erg
mut_set = {1, 2, 3}.into {Int; !3}
mut_set.insert!(4)
```
<p align='center'>
<a href='./13_record.md'>Previous</a> | <a href='./15_type.md'>Next</a>
</p>
</p>

View file

@ -1,7 +1,7 @@
# 类型
# types
类型在 Erg 中是一个非常重要的功能,因此我们提供了。请看那边。
Types are a very important feature in Erg, so we have a [dedicated section](./type/01_type_system.md). Please see there.
<p align='center'>
<a href='./14_set.md'>Previous</a> | <a href='./16_iterator.md'>Next</a>
</p>
<a href='./14_set.md'>Previous</a> | <a href='./16_iterator.md'>Next</a>
</p>

View file

@ -1,36 +1,33 @@
# 迭
迭代器是用于检索容器元素的对象。
# Iterator
An iterator is an object used to retrieve elements of a container.
```erg
for! 0..9, i =>
print! i
```
此代码输出 0 到 9 之间的数字。将每个数字(=Int 对象)赋给,并执行以下操作(=<gtr=7/>):这种重复执行称为<gtr=9/>
现在,我们来看一下过程的类型签名。
This code prints the numbers 0 through 9.
Each number (=Int object) is assigned to `i` and the following operation (=`print! i``) is executed. This kind of repetitive execution is called __iteration__.
Now let's look at the type signature of the `for!` procedure.
```erg
for!: |T: Type, I <: Iterable T| (I, T => None) => None
```
第一个参数似乎接受类型为的对象。
是具有<gtr=13/>属性和<gtr=14/>方法的请求方法类型。
The first argument seems to accept an object of type `Iterable`.
`Iterable` is a type with `.Iterator` attribute, `.iter` method in the request method.
```erg
Iterable T = Trait {
.Iterator = {Iterator}
.iter = Self(T).() -> Self.Iterator T
.iter = Self(T). () -> Self.Iterator T
}
```
属性类型<gtr=16/>是所谓的设置卡印(卡印在<gtr=17/>中描述)。
The type `{Iterator}` of the `.Iterator` attribute is so-called set-kind (kind is described [here](./type/advanced/kind.md)).
```erg
assert [1, 2, 3] in Iterable(Int)
@ -38,12 +35,13 @@ assert 1..3 in Iterable(Int)
assert [1, 2, 3].Iterator == ArrayIterator
assert (1..3).Iterator == RangeIterator
log [1, 2, 3].iter() # <ArrayIterator object>
log [1, 2, 3].iter() # <ArrayIterator object
log (1..3).iter() # <RangeIterator object>
```
<gtr=19/>都是实现<gtr=20/>的类,它们的存在只是为了赋予<gtr=21/><gtr=22/>小版本功能。这种设计模式称为伴随类<gtr=31/>。而<gtr=23/>修补程序是小版本功能的核心。<gtr=24/>只需要一个<gtr=25/>方法,<gtr=26/>实际上提供了几十个方法。<gtr=27/><gtr=28/>只需实现<gtr=29/>方法即可使用<gtr=30/>的实现方法。由于这种便利性,标准库实现了许多迭代器。
Both `ArrayIterator` and `RangeIterator` are classes that implement `Iterator` and exist only to give `Array` and `Range` iteration functions.
Such a design pattern is called companion class [<sup id="f1">1</sup>](#1).
And the `IteratorImpl` patch is the core of the iteration functionality. `Iterator` requires only one `.next` method, `IteratorImpl` provides dozens of methods indeed. `ArrayIterator` and `RangeIterator` can use the implementation method of `IteratorImpl` just by implementing the `.next` method. For this convenience, the standard library implements a number of iterators.
```mermaid
classDiagram
@ -80,11 +78,11 @@ classDiagram
Range <-- RangeIterator
```
提供一个接口的类型,如,在本例中为<gtr=33/>)是静态调度,但可以统一处理,这种类型称为伴随类适配器。
Types such as `Iterable` that provide an interface for handling traits (in this case `Iterator`) in a static dispatch yet unified manner are called companion class adapters.
---
<span id="1" style="font-size:x-small">1这个模式似乎没有统一的名字但在 Rust 中被称为,并以此为参照命名。</span>
<span id="1" style="font-size:x-small"><sup>1</sup> There doesn't seem to be a uniform name for this pattern, but in Rust, there is [companion struct pattern]( https://gist.github.com/qnighy/be99c2ece6f3f4b1248608a04e104b38#:~:text=%E3%82%8F%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%80%82-,companion%20struct,-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A8%E3%80%81%E3 %81%9D%E3%81%AE), and was named after it. [](#f1) </span>
<p align='center'>
<a href='./15_type.md'>Previous</a> | <a href='./17_mutability.md'>Next</a>

Some files were not shown because too many files have changed in this diff Show more