双周报Vlo.74:用于表示错误的 ! 语法被替换为关键字 raise、错误多态支持:高阶函数现可接受带错误的回调

语言更新

1、用于表示错误的 ! 语法被替换为关键字 raise

  • 用于表示错误的 ! 语法被替换为关键字 raise,具体的对应如下:
    • (..) -> T ! SomeErr => (..) -> T raise SomeErr
    • (..) -> T ! => (..) -> T raise
    • (..) -> T ? Error => (..) -> T raise?(这是近期新增的错误多态语法,不了解可以略过)
    • fn f!(..) { .. } => fn f(..) raise { .. }
    • fn!( ..) { .. } => fn (..) raise { .. }
      上述改动都可以通过格式化代码自动完成迁移

2、定义错误类型的语法 type! T .. 改为 suberror T ..

  • 定义错误类型的语法 type! T .. 改为 suberror T ..。这一改动可以通过格式化代码自动完成迁移

3、 f!(..)/ f?(..) 废弃警告及迁移注意事项

  • f!(..)f?(..) 语法被废弃,继续使用它们会收到编译器的警告。格式化代码能够自动去掉 ! 完成迁移,但 f?(..) 需要手动迁移至 try?。因为对于原先的 f?(g!(..)) 这种情况,简单改成 try? f(g(..)) 会改变语义,使 g 中的错误也被捕获。在手动迁移 f?(..)时,也需要特别注意这种情况

4、函数类型参数语法更新: fn f[..](..) 改为 fn[..] f(..)

  • 数周前,函数定义的类型参数的位置从 fn f[..](..) 改为 fn[..] f(..),和 impl 保持一致。现在,旧的写法被废弃并会收到编译器警告。这一改动可以通过格式化代码自动迁移

5、 typealiastraitalias语法更新:改用 as 替代 =

  • typealiastraitalias的语法进行了简化,typealias A = Btraitalias A = B 这两种写法被废弃,应改为使用 typealias B as Atraitalias B as A。复杂的 typealias,例如 typealias Matrix[X] = Array[Array[X]],应改为 typealias Array[Array[X]] as Matrix[X]。这一改动可以通过格式化代码自动迁移

6、废弃多参数 loop,改用元组参数以保持与 match 一致

  • 多参数的 loop 语法被废弃,应改为使用以元组为参数的 loop。这一改动让 loopmatch 更一致。MoonBit 编译器在 release 模式下能够通过优化消除掉 loop 中元组的开销,因此无需担心这一改动带来性能问题

7、显式实现特征(Trait)新规:即使有默认方法也需 impl

  • 对于那些 "每一个方法都有默认实现" 的特征(trait),之前,所有类型都会自动实现它们。但现在,即使一个特征的所有方法都有默认实现,也依然需要显式实现。如果没有需要提供自定义实现的方法,可以用impl Trait for Type 来表示 "给 Type 实现 Trait,但所有方法都用默认实现"。impl Trait for Type 也可以作为文档/TODO 使用,MoonBit 在看到这种声明时,会自动检查 Type 是否实现了 Trait,如果没有实现就报错

8、废弃外部类型 impl 的点调用,改用本地方法扩展

  • 之前,给外部类型的 impl 可以在当前包内用 . 调用。但这一功能是不重构安全的:上游新增方法会改变下游代码的行为。因此,我们决定废弃这一行为。作为替代,MoonBit 支持了局部地给外部类型定义新方法的功能,语法和普通的方法定义一样。这些给外部类型定义的方法有如下特点:

    • 它们不能是 pub 的。这是为了保证跨包协作时不会产生冲突
    • 如果上游(类型自身所在的包)已经定义了同名方法,编译器会报一个警告
    • 在解析方法调用时,本地方法的优先级最高

    这一修改之后,x.f(..) 的解析规则变为(优先级从高到低):

    • 本地的方法
    • x 的类型所在的包的方法
    • x 的类型所在的包的 impl

9、 Json字面量自动调用 ToJson::to_json,编写更便捷

  • Json 字面量内部,编译器会自动给不是字面量的表达式插入 ToJson::to_json 调用,写 Json 字面量时会更便捷:
rust 复制代码
let x = 42
// 之前
let _ : Json = { "x": x.to_json() }
// 现在
let _ : Json = { "x": x }

10、虚拟包支持抽象类型:接口声明,多实现可自定义类型

  • 虚拟包(virtual package)功能支持了抽象类型。可以在 .mbti 接口中声明抽象类型,并且不同的实现可以用不同的实际类型来实现接口中的抽象类型

11、 try可省略:简单表达式错误处理更简洁

  • 在处理简单表达式中的错误时,try 可以省略,直接写 f(..) catch { .. } 即可

12、新增保留字警告:未来可能成为关键字

  • 新增了一批保留字,它们目前不是关键字,但在未来可能成为关键字。如果在代码中使用这些名字,编译器会提出警告

下列改动目前尚未发布,将在 6.18 MoonBit beta release 之前发布

  • 新增了箭头函数语法 (..) => expr,能极大简化简单匿名函数:
rust 复制代码
test {
  let arr = [ 1, 2, 3 ]
  arr
  .map(x => x + 1) // 只有一个参数时可以省略括号
  .iter2()
  .each((i, x) => println("\{i}: \{x}"))
}
  • 矩阵函数功能被废弃,以精简语法。形如 fn { .. => expr } 的矩阵函数可以改为箭头函数,其他矩阵函数应改为显式的 fnmatch
  • 之前,可以使用 xx._ 语法来将 new type 转化为其实际表示。但这一语法和 partial application 语法(_.f(..))过于相似,有视觉歧义。因此,xx._ 语法被废弃,相应的,编译器会给每个 new type 自动生成一个 .inner() 方法,代替原本的 ._。这一改动可以通过格式化代码自动完成迁移
  • 对于一些比较模糊/不够广为人知的运算符优先级组合,例如 <<+,MoonBit 现在会产生警告。手动或者通过格式化代码加上括号来明确计算顺序即可消除警告
  • 新引入了 letrecand 关键字用于声明 local 互递归函数,比如:
rust 复制代码
fn main {
  letrec even = fn (x: Int) { ... } // anonymous function
  and odd = x => ...                // arrow function
}

等号右手侧只能是函数形式的值,比如匿名函数或者箭头函数,之前使用 fn 声明的隐式互递归写法会被 deprecated,不过自递归函数依然可以用 fn 进行声明。

  • fnalias 不再能用于创建非函数值的别名。对于非函数类型的值,可以用 let 来创建别名

标准库更新

1、错误多态支持:高阶函数现可接受带错误的回调

  • 利用新的错误多态功能,标准库中的许多高阶函数如 Array::each 现在可以接受带错误的回调函数了

工具链更新

  • main 包中支持写测试。moon test 会运行 main 包中的测试,moon run 则会运行 main 函数
  • IDE codelens 支持运行文档中的测试
  • moon testmoon check 现在默认会包含文档中的测试

经过深度打磨与社区反馈的持续优化,MoonBit Beta 版本将于6月18日正式发布,迈入语言稳定阶段,因此 MoonBit 双周报从下期起改为月报,请各位用户持续关注本专栏内容。

相关推荐
Mirageef14 小时前
aardio 模块化管理
编程语言
大熊猫侯佩18 小时前
Swift 5.9 中 if 与 switch 语句简洁新语法让撸码更带劲
swift·编程语言·apple
用户0595661192093 天前
深入理解Spring Boot框架:从基础到实践
java·spring·编程语言
whysqwhw3 天前
PlantUML 全面指南
编程语言
whysqwhw3 天前
ASCII图表及工具
编程语言
Mirageef4 天前
aardio 继承与多态
编程语言
大熊猫侯佩5 天前
Swift 中强大的 Key Paths(键路径)机制趣谈(下)
swift·编程语言·apple
Mirageef5 天前
aardio 类与对象基础
编程语言
Mirageef7 天前
aardio 自动识别验证码输入
编程语言