Skip to content

Commit

Permalink
Merge pull request #221 from moonbitlang/docs-error-handling
Browse files Browse the repository at this point in the history
docs for error handling
  • Loading branch information
Yu-zh authored Jun 25, 2024
2 parents 76f4546 + 90c1760 commit bc1b300
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,61 @@ match map {
- Map patterns are always open: unmatched keys are silently ignored
- Map pattern will be compiled to efficient code: every key will be fetched at most once

## Error Handling
The return type of a function can include an error type to indicate that the function might return an error. For example, the following function declaration indicates that the function div might return an error of type String:

```rust
fn div(x: Int, y: Int) -> Int!String {
if y == 0 {
raise "division by zero"
}
x / y
}
```

The keyword `raise` is used to interrupt the function execution and return an error. There are three ways to handle errors in functions:

* Using the `!!` suffix to panic directly in case of an error, for example:

```rust
fn div_unsafe(x: Int, y: Int) -> Int {
div(x, y)!! // Panic if `div` raised an error
}
```

* Using the `!` suffix to rethrow the error directly in case of an error, for example:

```rust
fn div_reraise(x: Int, y: Int) -> Int!String {
div(x, y)! // Rethrow the error if `div` raised an error
}
```

* Using `try` and `catch` to catch and handle errors, for example:

```rust
fn div_with_default(x: Int, y: Int, default: Int) -> Int {
try {
div(x, y)!
} catch {
s => { println(s); default }
}
}
```

Here, `try` is used to call a function that might throw an error, and `catch` is used to match and handle the caught error. If no error is caught, the catch block will not be executed.

In MoonBit, error types and error handling are second-class citizens, so error types can only appear in the return value of functions and cannot be used as the type of variables. Error handling with the `!` or `!!` suffix can only be used at the function call site and not in other expressions. Valid usage forms include:

```rust
f(x)!
x.f()!
(x |> f)!
(x + y)!
```

Additionally, if the return type of a function includes an error type, the function call must use `!` or `!!` for error handling, otherwise the compiler will report an error.

## Generics

Generics are supported in top-level function and data type definitions. Type parameters can be introduced within square brackets. We can rewrite the aforementioned data type `List` to add a type parameter `T` to obtain a generic version of lists. We can then define generic functions over lists like `map` and `reduce`.
Expand Down
51 changes: 51 additions & 0 deletions zh-docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,57 @@ match map {
- 字典模式永远是开放的:未被匹配到的键会被忽略
- 字典模式会被编译成高效的代码:每个键至多被查询一次

## 错误处理

函数的返回值类型中可以包含错误类型,用于表示函数可能返回的错误。比如如下函数声明表示函数 `div` 可能返回一个字符串类型的错误:

```rust
fn div(x: Int, y: Int) -> Int!String {
if y == 0 {
raise "division by zero"
}
x / y
}
```

其中 `raise` 关键字用于中断函数的执行并返回一个错误。函数的错误处理有以下三种方式:

* 使用 `!!` 后缀来在发生错误的情况下直接 panic,比如
```rust
fn div_unsafe(x: Int, y: Int) -> Int {
div(x, y)!! // 直接 panic
}
```

* 使用 `!` 后缀来在发生错误的情况下将错误直接重新抛出,比如
```rust
fn div_reraise(x: Int, y: Int) -> Int!String {
div(x, y)! // 直接重新抛出错误
}
```

* 使用 `try``catch` 对错误进行捕获并处理,比如
```rust
fn div_with_default(x: Int, y: Int, default: Int) -> Int {
try {
div(x, y)!
} catch {
s => { println(s); default }
}
}
```
其中 `try` 用于调用可能会抛出错误的函数,`catch` 用于对捕获的错误进行模式匹配并处理,如果没有捕获到错误则不会执行 `catch` 语句块。

在 MoonBit 中,错误类型和错误处理属于二等公民,因此错误类型只能出现在函数的返回值中,而不能作为变量的类型。使用后缀表达式 `!``!!` 进行的错误处理也只能在函数调用处进行,而不能在其他表达式中使用,合法的使用形式包括:
```rust
f(x)!
x.f()!
(x |> f)!
(x + y)!
```

此外,如果函数的返回值类型中包含错误类型,那么对该函数的调用必须使用 `!``!!` 进行错误处理,否则编译器会报错。

## 泛型

您可以在顶层的函数和数据结构定义中使用泛型。类型参数可以由方括号引入。
Expand Down

0 comments on commit bc1b300

Please sign in to comment.