Skip to content

Commit

Permalink
Merge pull request #110 from KKKZOZ/main
Browse files Browse the repository at this point in the history
Format zh-docs
  • Loading branch information
bzy-debug authored Nov 21, 2023
2 parents b61b366 + 93675cd commit 4bcca80
Showing 1 changed file with 47 additions and 48 deletions.
95 changes: 47 additions & 48 deletions zh-docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ MoonBit 目前处于 Pre-alpha 阶段,是实验性质的。我们期望明年
## 概述

一个月兔程序由类型定义,函数定义和变量绑定组成。
每个包的入口点是一个特殊的`init`函数。`init`函数特殊在以下两个方面:
每个包的入口点是一个特殊的 `init` 函数。`init` 函数特殊在以下两个方面:

1. 在同一个包中可以有多个 `init` 函数。
1. `init` 函数不能被显式地调用或被其他函数引用。相反,在一个包初始化时,所有的`init`函数都将被隐式地调用。因此,`init`函数只应该包含语句。
1. `init` 函数不能被显式地调用或被其他函数引用。相反,在一个包初始化时,所有的 `init` 函数都将被隐式地调用。因此,`init` 函数只应该包含语句。

```rust live
fn init {
Expand Down Expand Up @@ -60,19 +60,19 @@ fn init {

- 值字面量(例如布尔值、数字、字符、字符串、数组、元组、结构体)
- 算术、逻辑或比较操作
- 访问数组元素(例如`a[0]`)或结构体字段(例如`r.x`)或元组组成部分(例如`t.0`
- 访问数组元素(例如 `a[0]`)或结构体字段(例如 `r.x`)或元组组成部分(例如 `t.0`
- 变量和(大写字母开头的)枚举构造器
- 匿名局部函数定义
- `match``if`表达式
- `match``if`表达式

语句包括:

- 命名局部函数定义
- 局部变量绑定
- 赋值
- While 循环和相关的控制流结构(`break``continue`
- `return`语句
- 返回类型为`unit`的任何表达式
- While 循环和相关的控制流结构(`break``continue`
- `return` 语句
- 返回类型为 `unit` 的任何表达式

## 函数

Expand All @@ -81,9 +81,8 @@ fn init {

### 顶层函数

Functions can be defined as top-level or local.
函数可以被定义为顶层或局部。
我们可以使用`fn`关键字定义一个顶层函数,
我们可以使用 `fn` 关键字定义一个顶层函数,
例如以下求三个整数之和并返回结果的函数:

```rust
Expand All @@ -92,11 +91,11 @@ fn add3(x: Int, y: Int, z: Int)-> Int {
}
```

注意顶层函数的参数和返回值类型需要显式标注。如果返回类型被省略,函数将被视为返回`unit`类型。
注意顶层函数的参数和返回值类型需要显式标注。如果返回类型被省略,函数将被视为返回 `unit` 类型。

### 局部函数

局部函数使用`fn`关键字定义。局部函数可以是命名或匿名的。在大多数情况下,局部函数的类型注解可以省略,因为编译器可以自动推断。例如:
局部函数使用 `fn` 关键字定义。局部函数可以是命名或匿名的。在大多数情况下,局部函数的类型注解可以省略,因为编译器可以自动推断。例如:

```rust live
fn foo() -> Int {
Expand Down Expand Up @@ -142,7 +141,7 @@ fn init {
}
```

表达式`add3(1, 2, 7)`返回`10`。任何求值为函数值的表达式都可以被调用:
表达式 `add3(1, 2, 7)` 返回 `10`。任何求值为函数值的表达式都可以被调用:

```rust live
fn init {
Expand All @@ -156,7 +155,7 @@ fn init {

### 条件表达式

条件表达式由条件、结果和一个可选的`else`子句组成。
条件表达式由条件、结果和一个可选的 `else` 子句组成。

```rust
if x == y {
Expand All @@ -170,7 +169,7 @@ if x == y {
}
```

`else`子句也可以包含另一个`if-else`表达式:
`else` 子句也可以包含另一个 `if-else` 表达式:

```rust
if x == y {
Expand All @@ -182,20 +181,20 @@ if x == y {

花括号在结果或 `else` 子句中用于组合表达式

需要注意的是,在 MoonBit 中,条件表达式总是返回一个值,结果和`else`子句的返回值类型必须相同。
需要注意的是,在 MoonBit 中,条件表达式总是返回一个值,结果和 `else` 子句的返回值类型必须相同。

### 循环

MoonBit 中的主要循环语句是 while 循环:
MoonBit 中的主要循环语句是 `while` 循环:

```rust
while x == y {
expr1
}
```

while 语句不返回任何值;它只求值成`unit`类型的`()`
MoonBit 还提供`break``continue`语句来控制循环流。
`while` 语句不返回任何值;它只求值成 `unit` 类型的 `()`
MoonBit 还提供 `break``continue` 语句来控制循环流。

## 内置数据结构

Expand All @@ -207,22 +206,22 @@ Moonbit 支持数字的字面量,包括十进制,二进制,八进制和十

- 十进制数没有任何出人意料的地方。

```
```rust
let a = 1234
let b = 1_000_000 + a
let large_num = 9_223_372_036_854_775_807L // Int64 类型的整数必须有'L'作为后缀
```

- 一个八进制数有一个前缀 0 接着一个字母 O,也就是 `0o``0O`。注意到在 `0o``0O` 之后出现的数字只能在 `0``7` 之间。

```
```rust
let octal = 0o1234
let another_octal = 0O1234
```

- 一个十六进制数有一个前缀 0 接着一个字母 X,也就是 `0x``0X`。注意到在 `0x``0X` 之后出现的数字只能是 `0123456789ABCDEF` 之一。

```
```rust
let hex = 0XA
let another_hex = 0xA
```
Expand All @@ -242,8 +241,8 @@ fn init {

### 元组

元组是一个有限值的集合,使用圆括号`()`构造,其中元素由逗号`,`分隔。
元素的顺序很重要,例如`(1, true)``(true, 1)`是不同的类型。以下是一个例子:
元组是一个有限值的集合,使用圆括号 `()` 构造,其中元素由逗号 `,` 分隔。
元素的顺序很重要,例如 `(1, true)``(true, 1)` 是不同的类型。以下是一个例子:

```rust live
fn pack(a: Bool, b: Int, c: String, d: Double) -> (Bool, Int, String, Double) {
Expand Down Expand Up @@ -277,13 +276,13 @@ fn init {

### 数组

数组是由方括号`[]`构造的有限值序列,其中元素由逗号`,`分隔。例如:
数组是由方括号 `[]` 构造的有限值序列,其中元素由逗号 `,` 分隔。例如:

```rust
let array = [1, 2, 3, 4]
```

可以使用`array[x]`来引用第 x 个元素。索引从零开始。
可以使用 `array[x]` 来引用第 x 个元素。索引从零开始。

```rust live
fn init {
Expand All @@ -297,7 +296,7 @@ fn init {

## 变量绑定

变量可以使用关键字`var``let`分别声明为可变或不可变。
变量可以使用关键字 `var``let` 分别声明为可变或不可变。
可变变量可以重新赋值,不可变变量则不能。

```rust live
Expand All @@ -310,7 +309,7 @@ fn init {
}
```

对于局部不可变绑定,还可以使用`:=`的简写语法糖。
对于局部不可变绑定,还可以使用 `:=` 的简写语法糖。

```rust live
fn init {
Expand All @@ -323,15 +322,15 @@ fn init {

## 数据类型

创建新数据类型的方法有两种:`struct``enum`
创建新数据类型的方法有两种:`struct``enum`

### 结构

在 MoonBit 中,结构与元组类似,但是它们的字段由字段名索引。
结构体可以使用结构体字面量构造,结构体字面量由一组带有标签的值组成,并用花括号括起来。
如果结构体字面量的字段完全匹配类型定义,则其类型可以被自动推断。
使用点语法 s.f 可以访问结构体字段。
如果一个字段使用关键字 mut 标记为可变,那么可以给它赋予新的值。
使用点语法 `s.f` 可以访问结构体字段。
如果一个字段使用关键字 `mut` 标记为可变,那么可以给它赋予新的值。

```rust live
struct User {
Expand Down Expand Up @@ -395,8 +394,8 @@ fn init {

我们已经展示了对枚举进行模式匹配的用例,但是模式匹配不局限于枚举。
例如,我们也可以对布尔值、数字、字符、字符串、元组、数组和结构体字面量进行模式匹配。
由于这些类型和枚举不同,只有一种情况,我们可以使用`let`/`var`绑定而不是`match`表达式来对它们进行模式匹配。
需要注意的是,在`match`中绑定的变量的作用域仅限于引入该变量的分支,而`let`/`var`绑定将引入每个变量到当前作用域。
由于这些类型和枚举不同,只有一种情况,我们可以使用 `let`/`var` 绑定而不是 `match` 表达式来对它们进行模式匹配。
需要注意的是,在 `match` 中绑定的变量的作用域仅限于引入该变量的分支,而 `let`/`var` 绑定将引入每个变量到当前作用域。
此外,我们可以使用下划线 `_` 作为我们不关心的值的通配符。

```rust
Expand All @@ -408,7 +407,7 @@ let { id: id, name: _, email: _ } = u
```

在模式匹配中还有一些其他有用的构造。
例如,我们可以使用`as`为某个模式指定一个名称,并且可以使用`|`同时匹配多个情况。
例如,我们可以使用 `as` 为某个模式指定一个名称,并且可以使用 `|` 同时匹配多个情况。

```rust
match expr {
Expand All @@ -422,8 +421,8 @@ match expr {

您可以在顶层的函数和数据结构定义中使用泛型。
类型参数可以由方括号引入。
我们可以重写前面提到的数据类型`List`,添加类型参数`T`,以获得一个泛型版本的列表。
然后,我们可以定义泛型函数`map``reduce`,用于对列表进行操作。
我们可以重写前面提到的数据类型 `List`,添加类型参数 `T`,以获得一个泛型版本的列表。
然后,我们可以定义泛型函数 `map``reduce`,用于对列表进行操作。

```rust
enum List[T] {
Expand All @@ -449,11 +448,11 @@ fn reduce[S, T](self: List[S], op: (T, S) => T, init: T) -> T {
## 统一函数调用语法

MoonBit 支持与传统面向对象语言不同的方法(method)。
一个方法被定义为`self`作为其第一个参数的顶层函数。
`self`参数将成为方法调用的主体。
例如,`l.map(f)`等同于`map(l, f)`
一个方法被定义为 `self` 作为其第一个参数的顶层函数。
`self` 参数将成为方法调用的主体。
例如,`l.map(f)` 等同于 `map(l, f)`
这种语法使得方法链而不是嵌套的函数调用成为可能。
例如,我们可以使用这样的语法将先前定义的`map``reduce``from_array``output`方法链在一起,执行列表操作。
例如,我们可以使用这样的语法将先前定义的 `map``reduce``from_array``output` 方法链在一起,执行列表操作。

```rust live
fn map[S, T](self: List[S], f: (S) -> T) -> List[T] {
Expand Down Expand Up @@ -486,12 +485,12 @@ fn init {
```

方法和普通函数的另一个区别是,只有方法支持重载。
例如,我们可能需要多个输出函数:`output_int``output_float`用于不同类型的输出。
但使用方法`output`,可以识别主体的类型,并选择适当的重载版本,例如 print(1) 和 print(1.0)。
例如,我们可能需要多个输出函数: `print_int``print_float` 用于不同类型的输出。
但使用方法 `print` ,可以识别主体的类型,并选择适当的重载版本,例如 `print(1)``print(1.0)`

## 运算符重载

MoonBit 支持重载内置运算符。与运算符`<op>`相对应的方法名称是`op_<op>`。例如:
MoonBit 支持重载内置运算符。与运算符 `<op>` 相对应的方法名称是 `op_<op>`。例如:

```rust live
struct T {
Expand Down Expand Up @@ -527,11 +526,11 @@ fn init {
默认情况下,所有函数定义和变量绑定对其他包是 _不可见_ 的;
没有修饰符的类型是抽象数据类型,其名称被导出,但内部是不可见的。
这种设计防止了意外暴露实现细节。
您可以在`type`/`fn`/`let`前使用`pub`修饰符使其完全可见,或在`type`前使用`priv`修饰符使其对其他包完全不可见。
您还可以在字段名前使用`pub``priv`获得更细粒度的访问控制。
您可以在 `type`/`fn`/`let` 前使用 `pub` 修饰符使其完全可见,或在 `type` 前使用 `priv` 修饰符使其对其他包完全不可见。
您还可以在字段名前使用 `pub``priv` 获得更细粒度的访问控制。
但是,请注意:

- 在抽象或私有结构体内,所有字段都不能被定义为`pub`,因为这样没有意义。
- 在抽象或私有结构体内,所有字段都不能被定义为 `pub`,因为这样没有意义。
- 枚举类型的构造器没有单独的可见性,所以不能在它们前面使用 `pub``priv`

```rust
Expand Down Expand Up @@ -572,7 +571,7 @@ priv enum T3 { // explicitly private enum
}
```

MoonBit 中另一个有用的特性是 `pub(readonly)` 类型,其受到了 OCaml [private types](https://v2.ocaml.org/manual/privatetypes.html)的启发。简而言之,`pub(readonly)`类型的值可以使用模式匹配或点语法析构,但在其他包中,不能被构造或改变。注意到在`pub(readonly)`类型定义的同一个包中,它没有任何限制。
MoonBit 中另一个有用的特性是 `pub(readonly)` 类型,其受到了 OCaml [private types](https://v2.ocaml.org/manual/privatetypes.html)的启发。简而言之,`pub(readonly)` 类型的值可以使用模式匹配或点语法析构,但在其他包中,不能被构造或改变。注意到在 `pub(readonly)` 类型定义的同一个包中,它没有任何限制。

```rust
// Package A
Expand All @@ -596,8 +595,8 @@ fn init {
}
```

MoonBit 中的访问控制遵循这样一个原则:`pub`类型、函数或变量不能基于私有类型进行定义。
这是因为私有类型可能不是在使用`pub`实体的所有地方都可以被访问。
MoonBit 中的访问控制遵循这样一个原则:`pub` 类型、函数或变量不能基于私有类型进行定义。
这是因为私有类型可能不是在使用 `pub` 实体的所有地方都可以被访问。
MoonBit 内建了一些检查,以防止违反这一原则的用例。

```rust
Expand Down

0 comments on commit 4bcca80

Please sign in to comment.