Int!String
来标识这个函数正常情况下返回 Int
,错误情况下会抛出类型为 String
的错误值,比如fn div(x: Int, y: Int) -> Int!String { .. }
raise
关键字用于中断当前控制流,直接抛出错误,比如fn div(x: Int, y: Int) -> Int!String {
if y == 0 { raise "divide by 0" }
x / y
}
try { expr0 } catch { pattern1 => expr1; pattern2 => expr2; .. }
表达式可以用于捕获 expr0
中抛出的错误,并对其进行模式匹配来处理,比如下面这个函数调用上面的 div
函数,并在 div
函数抛出错误的时候将错误信息打印,并返回默认值fn div_with_default(x: Int, y: Int, default: Int) -> Int {
try {
div(x, y)!
} catch {
s => { println(s); default }
}
}
!
和 !!
进行错误处理,这些后缀运算符只能应用于函数调用,其中:
f(x)!
将调用 f
的过程中发生的错误立即重新抛出,其等价于try { f(x)! } catch { err => raise err }
f(x)!!
则会在 f
发生错误的情况下直接 panic ,其等价于
try { f(x)! } catch { _ => panic() }
函数调用的形式包括方法调用,中缀运算符和管道运算符的调用,比如
fn init {
let _ = x.f()!!
let _ = (x + y)!!
let _ = (x |> f)!!
}
Map
字面量语法:fn init {
// 键必须是字面量
let m1 : Map[String, Int] = { "x": 1, "y": 2 }
let m2 : Map[Int, String] = { 1: "x", 2: "y" }
}
修复了 IDE 在补全过程中 builtin package 中的方法会重复出现两次的 bug
修复了 IDE 中缺少 Byte 相关的补全功能
添加对 internal 包的支持,这些包被放在名为 internal
的目录中。internal 包只能被以 internal
的父目录为根的包导入。
例如,如果有一个包的路径为 username/hello/x/internal/a
,该 internal 包的父目录为 username/hello/x
,那么只有包username/hello/x
或其子包(例如 username/hello/x/a
)能够导入username/hello/x/internal/a
,而username/hello/y
则不能导入该包。
1
w568w 165 天前
这个错误处理的设计是出于什么思想?看起来很像 Ziglang/Rust 的「错误即返回值」模式和传统的 Exception 模式杂糅在一起……
如何保证不会提高处理错误的复杂度?原先只需要考虑一种错误,现在要同时考虑两种可能的异常程序流了 |
2
w568w 165 天前
补充一句:感觉最后可能会演变成,第三方库分为 return 派和 raise 派各自为政……
|