From d27172121dad9004a0a58afd7da2e01632259996 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 5 Jul 2024 17:49:05 +0800 Subject: [PATCH] update `!!` --- README.md | 26 ++++++++++++++++++-------- zh-docs/README.md | 24 +++++++++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 65c52fe6..ddf86ba3 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/zh-docs/README.md b/zh-docs/README.md index cc561740..318e99ff 100644 --- a/zh-docs/README.md +++ b/zh-docs/README.md @@ -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 { @@ -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)!