Skip to content

Commit

Permalink
Merge pull request #240 from moonbitlang/fix-error
Browse files Browse the repository at this point in the history
update `!!`
  • Loading branch information
Yu-zh authored Jul 5, 2024
2 parents c07a191 + d271721 commit 8ec4e34
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1002,14 +1002,6 @@ fn div(x: Int, y: Int) -> Int!String {

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:

```moonbit
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:

```moonbit
Expand All @@ -1032,6 +1024,24 @@ fn div_with_default(x: Int, y: Int, default: Int) -> Int {

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.

* Using the `!!` suffix to convert the result into a first-class value of the `Result` type, for example:

```moonbit
test {
let res = div(6, 3)!!
inspect(res, content="Ok(2)")!
let res = div(6, 0)!!
inspect(res, content="Err(division by zero)")!
}
```

The suffix `!!` is a syntax sugar that is equivalent to the following code:
```moonbit
test {
let res = try { Ok(div(6, 3)!) } catch { s => Err(s) }
}
```

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:

```moonbit
Expand Down
24 changes: 17 additions & 7 deletions zh-docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1011,13 +1011,6 @@ fn div_unsafe(x: Int, y: Int) -> Int {
}
```

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

* 使用 `try``catch` 对错误进行捕获并处理,比如
```moonbit
fn div_with_default(x: Int, y: Int, default: Int) -> Int {
Expand All @@ -1030,6 +1023,23 @@ fn div_with_default(x: Int, y: Int, default: Int) -> Int {
```
其中 `try` 用于调用可能会抛出错误的函数,`catch` 用于对捕获的错误进行模式匹配并处理,如果没有捕获到错误则不会执行 `catch` 语句块。

* 使用 `!!` 后缀来将函数执行结果转化为 `Result` 类型的值,比如:
```moonbit
test {
let res = div(6, 3)!!
inspect(res, content="Ok(2)")!
let res = div(6, 0)!!
inspect(res, content="Err(division by zero)")!
}
```

本质上,后缀表达式 `!!` 是下面代码的语法糖:
```moonbit
test {
let res = try { Ok(div(6, 3)!) } catch { s => Err(s) }
}
```

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

0 comments on commit 8ec4e34

Please sign in to comment.