跳到主要内容

weekly 2024-07-01

· 阅读需 2 分钟

MoonBit 更新

  • 在没有歧义的情况下,enum构造器的使用可以省略类型前缀。比如现在可以直接使用 Some(42) 而不需要写 Option::Some(42);如果当前环境中有两个类型 T1T2 都定义了某个构造器 C,那么在使用的时候则需要通过上下文中的类型或者类型前缀指明是 T1::C 还是 T2::C,否则编译器会报错

  • 添加 UInt64 内建类型,支持加、减、乘、除、模以及 UInt64/Int64 的互相转换。

fn main {
  let a = 0UL
  let b : UInt64 = 1UL
  println(a - b) //18446744073709551615
}
  • !! 后缀的语义修改为捕获函数调用中可能出现的错误,并返回 Result 类型,比如
fn f() -> Int!String { .. }
fn main {
  let res = f()!! // res: Result[Int, String]
  println(res)
}
  • moon test 中支持使用错误类型表示测试失败的情况,比如
fn eq[T : Debug + Eq](a : T, b : T, ~loc : SourceLoc = _) -> Unit!String {
  if a != b {
    let a = debug_string(a)
    let b = debug_string(b)
    raise ("FAILED: \(loc) `\(a) == \(b)`")
  }
}

test "test_eq" {
  eq(1+2, 3)!
}
  • 标准库中的 I/O 相关操作只保留了 println,其他操作将会在 io package 中提供

标准库更新

  • 统一 T::new()/T::make() 等创建容器对象的函数风格,移除了 T::with_capacity

  • 原先的 iteriteri 重命名为 eacheachiiter_reviter_revi 重命名为 each_reveachi_rev

  • as_iter 重命名为iter

构建系统更新

  • 预计将于本周开源

工具链更新

  • 优化调试体验,现在⽤户可在 JavaScript Debug Terminal 中执⾏ moon run --target js --debug 进行调试

  • moon info 和覆盖率工具适配错误类型和错误处理

weekly 2024-06-24

· 阅读需 1 分钟

MoonBit 更新

  • 支持了 32 位无符号整数
let num = 100U // 32位无符号整数的字面量需要后缀U
  • 在 wasm 后端导出返回值类型为 Unit 的函数时,之前导出函数的类型中会有 (result i32),现在 MoonBit 编译器会自动生成一个没有返回值 wrapper 函数,并将其进行导出

  • moonbitlang/core 的 API 一致性调整

    • forall/existall/any统一为all/any
    • containsmember 统一为contains

IDE 更新

  • 修复了 rename method 时候会丢失 type prefix 的 bug

  • 增加了 try ... catch ... 表达式中的 match clause 中补全的功能

构建系统更新

  • 增加了诊断信息渲染功能,目前还在试验阶段。可通过设置环境变量 MOON_RENDR=1 启用

diagnosis.png

  • moon bench 命令改为 moon generate-build-matrix,bench 子命令留待后续使用

weekly 2024-06-17

· 阅读需 3 分钟

MoonBit 更新

  • 支持了错误处理机制
  1. 函数返回值类型可以用 Int!String 来标识这个函数正常情况下返回 Int ,错误情况下会抛出类型为 String 的错误值,比如
fn div(x: Int, y: Int) -> Int!String { .. }
  1. raise 关键字用于中断当前控制流,直接抛出错误,比如
fn div(x: Int, y: Int) -> Int!String {
  if y == 0 { raise "divide by 0" }
  x / y
}
  1. 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 }
  }
}
  1. 此外,可以用后缀运算符 !!! 进行错误处理,这些后缀运算符只能应用于函数调用,其中: f(x)! 将调用 f 的过程中发生的错误立即重新抛出。 f(x)!! 则会在 f 发生错误的情况下直接 panic,其等价于
try { f(x)! } catch { _ => panic() }

函数调用的形式包括方法调用,中缀运算符和管道运算符的调用,比如

fn init {
  let _ = x.f()!!
  let _ = (x + y)!!
  let _ = (x |> f)!!
}
  1. 最后,对可能会抛出错误的函数如果没有使用上述任何错误处理,那么则会报 unhandled error 的错误
  • 支持 Map 字面量语法:
fn init {
  // 键必须是字面量
  let m1 : Map[String, Int] = { "x": 1, "y": 2 }
  let m2 : Map[Int, String] = { 1: "x", 2: "y" }
}

IDE更新

  • 修复了 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则不能导入该包。

weekly 2024-06-11

· 阅读需 2 分钟

MoonBit更新

  • 【Wasm MVP】Wasm1 后端添加基于 Perceus 算法的引用计数支持

  • 【语法】throw raise try catch 均被保留为关键字

    • 为了即将添加的错误处理机制
  • 【Core】Listsorted_map被移动至core/immut

    • List被移动至core/immut/list包中,并被移除内置类型支持
    
    let a = @immut/list.List::Cons(1, Cons(2, Nil))
    
    
    • sorted_map被移动至core/immut/sorted_map包中
  • 【Core】JSON API被优化,以提高性能并适应新的Core API

    • 新的类型定义
// Types and methods
pub enum JsonValue {
  Null
  // 原为Boolean(Bool)
  True
  False
  Number(Double)
  String(String)
  Array(Array[JsonValue])
  Object(Map[String, JsonValue]) // 原为@map.Map
}
  • 【JS】Int64性能优化
    • 在 JS 后端上,Int64现编译到两个Int,解决原先编译到BigInt的性能问题。同时,JS 下Int64的 runtime 实现现移动到 core 标准库中,便于开源社区参与 review 和改进。

构建系统更新

  • moon.mod.json 和 moon.pkg.json 在开发过程中支持注释,但是在 publish 时不允许注释(只支持标准 JSON 格式)

IDE更新

  • 【LSP】函数补全增加参数名称显示 LSP.png

weekly 2024-06-03

· 阅读需 2 分钟

MoonBit更新

  • 类型标注增加了新的语法T? 来表示Option[T]
struct Cell[T] {
  val: T
  next: Cell[T]?
}

fn f(x : Cell[T]?) -> Unit { ... }

相当于

struct Cell[T] {
  val: T
  next: Option[Cell[T]]
}

fn f(x : Option[Cell[T]]) -> Unit { ... }

旧的Option[T]仍然兼容,但是推荐使用更简短的新语法。moonfmt也会将Option[T]格式化为T?

  • 核心库 API 整理工作继续进行
    • Iter包被合入了builtin包。现在使用Iter[T]不需要@iter.前缀
pub fn any[T](xs : Iter[T], predicate : (T) -> Bool) -> Bool {
                // ^不需要@iter.
  match xs.find_first(predicate) {
    None => false
    Some(_) => true
  }
}
  • Stack包被移入moonbitlang/x
  • 移除了List包,以及各类数据结构的to_listfrom_list函数。对于数据结构间转换和中间的表示结构,推荐使用Iter[T]Array[T]
  • 性能提升
    • 编译器现在会在分离编译的阶段进行一部分的闭包转化,从而改进了编译性能,并且对 JavaScript 后端生成的代码在特定情况下也进行了闭包转化
    • Option[Bool], Option[Char], Option[Byte], Option[Unit] 这些类型使用32位整数表示,其中 None 对应的值为 -1, Some(x) 对应的值为 x; Option[Int] 类型在 wasm 后端使用 64 位整数表示,其中 None 对应的值为 0x1_0000_0000, Some(x) 对应的值为 x, Option[Int]在 JavaScript 后端使用 int | undefined 表示,其中 undefined 表示 None
  • abort行为变更
    • 为了解除Wasm程序对于非标准的spectest.print_char的依赖,正在重构错误输出功能。
    • abort将不会利用spectest.print_char打印错误信息,行为与panic相同,等待功能进一步完善。

插件更新

  • 【语言服务器】修复了内存泄露的问题

weekly 2024-05-27

· 阅读需 2 分钟

MoonBit 周报 Vol.42:核心库进行API整理工作、工具链持续完善

MoonBit更新

  • 【核心库 Breaking】核心库进行API整理工作
    • 所有immutable数据结构被放在immut路径下,如@immutable_hashmap.Map变为@immut/hashmap.Map
// Before
let a : @immutable_hashmap.Map[Int, Int] = @immutable_hashmap.make()
// After
let a : @immut/hashmap.Map[Int, Int] = @immut/hashmap.make()
  • 核心库中 Option[T] 类型性能优化
    • 在类型 T 是一个引用类型情况下,对于 Option[T] 类型的值,Some(v) 会被直接编译成 vNone 会在 wasm-gc 后端被编译成 ref.null ,在 JavaScript 后端被编译成 undefined,从而避免内存分配
  • 核心库中引入了 fn panic[T]() -> T 函数,这个函数可以用于在测试块中,其中测试的名字需要以 "panic" 开头:
test "panic test ok" {
  panic() // 测试通过
}

test "panic test failed" {
  () // 测试失败
}

IDE更新

  • 【VS Code插件】增加了testfor的代码片段 test片段 test.gif for片段 for.gif

构建系统更新

  • 【初始化】moon new 会自动对创建的项目进行版本控制初始化,目前支持 git
  • 【测试】现在可以指定对多个包进行测试
moon test -p a b c
moon test -p a -p b -p c

工具链更新

  • 【安装】现在可以指定版本号进行安装
# Mac与Linux用户
# 下载最新版
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
# 下载 bleeding 版本
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s bleeding
# 下载特定版本
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s 0.1.20240520+b1f30d5e1
# Windows用户
# 下载最新版
irm cli.moonbitlang.cn/install/powershell.ps1 | iex
# 下载特定版本
$env:MOONBIT_INSTALL_VERSION = "0.1.20240520+b1f30d5e1"; irm cli.moonbitlang.cn/install/powershell.ps1 | iex

weekly 2024-05-20

· 阅读需 3 分钟

MoonBit更新

  • 【Breaking Change】Array重命名为FixedArray@vec.Vec重命名为Array
// Before
fn init {
  let array : @vec.Vec[Int] = [1, 2, 3]
}
// After
fn main {
  let array : Array[Int] = [1, 2, 3]
}
  • 【语法】键值对(如Map HashMap等)增加模式匹配支持
    • 类型需实现op_get方法,其键为原生类型(Int Char String Bool等),值为Option[T]
    • 匹配时,键需为字面量
    • { "key": pat } 中,模式 pat 类型是 Option[T]None表示 "key"不存在,Some(p)表示 "key"存在,且 p 会被用于匹配这个键的值
    • 匹配键值对的模式都是开放的:未被匹配的键即使存在也会被忽略掉
    • 键值对模式会生成优化过的代码,每个键至多被查询一次
fn main {
  let map = @map.Map::[ ("a", 1) ]
  match map {
    // 当 `map` 包含 "b" 时匹配,
    // 并把 "b" 在 `map` 中的值绑定到 `y`
    { "b": Some(y) } => println(y)
    // 当 `map` 不包含 "b" 而包含 "a" 时匹配,
    // 并把 "a" 的值绑定到 `k`
    { "b": None, "a": Some(k) } => println(k)
    // 编译器提示 { "b": None, "a": None } 的情况未被匹配到
  }
  // 输出:1
}
  • 【语法】允许在已知类型信息的情况下省略newtype构造器
type A Int

pub fn op_add(self : A, other : A) -> A {
  self.0 + other.0 // 省略构造器
}

fn main {
  A::A(0) + 1 |> ignore // 省略 1 的构造器
  let _c : A = 0 + 1 + 2
}

构建系统更新

  • 配置文件选项统一为kebab-case(近期仍对snake_case保持兼容)
{
  "is-main": true,
  "test-import": []
}
  • 【Wasm,Wasm-GC】后端支持在moon.pkg.json中指定导出内存名称(默认为moonbit.memory)与编译选项(如-no-block-params以兼容binaryen工具链)
{
 "link": {
  "wasm": {
  "export-memory-name": "custom_memory_name",
  "flags": ["-no-block-params"]
 },
}
  • moon check 增加 --deny-warn 选项,在有 warning 时视为失败,返回非0值
  • moon fmt 增加 --check选项,用于检查当前代码是否已被格式化

标准库更新

  • 增加实验性库moonbitlang/x,用于开发与测试API不稳定的包。moonbitlang/x中的包稳定后,我们会根据社区的意见,选取重要的包合入moonbitlang/core
    • num time uuid json5 均已移动至moonbitlang/x
  • Bytes API 变更,从Int迁移到了Byte类型:
fn Bytes::op_get(self : Bytes, index : Int) -> Byte
fn Bytes::op_set(self : Bytes, index : Int, value : Byte) -> Unit
fn Bytes::length(self : Bytes) -> Int
fn Bytes::make(len : Int, ~init : Byte = b'\x00') -> Bytes

weekly 2024-05-13

· 阅读需 3 分钟

MoonBit更新

  • 支持了构造器的 payload 中出现 mutable field,使用方式如下:
enum E {
  C(mut ~x : Int, mut ~y : Int)
} derive(Debug)


fn swap_xy(x : E) -> Unit {
  match x {
    // `~y` 会绑定模式匹配前 `C` 中的 `y` 字段的值
    // 当看到 `C(..) as c` 这种模式时,编译器知道 `c` 一定是构造器 `C`,
    // 所以可以在分支内部用 `c.x`、`c.y` 直接访问 `C` 的字段
    C(~y, ..) as c => {
      // `c.x` 和 `c.y` 可以用于修改/读取 `C` 中最新的值
      c.y = c.x
      c.x = y
    }
  }
}

fn init {
  let e : E = C(x=1, y=2)
  debug(e) // C(x=1, y=2)
  swap_xy(e)
  debug(e) // C(x=2, y=1)
}

这个例子中的 swap_xy 函数对构造器 Cxy 两个 field 的值进行了交换,并且这个交换是 in-place 的,没有引入额外的内存分配

  • **数组字面量默认构建 vector。**对 Array literal 语法进行了重载,现在 Array literal 可以用来构造 Vector 或者 Array,具体的类型通过上下文决定,当上下文中类型信息不明确时,默认使用 Vector,比如
fn init {
  let v = [1, 2, 3]             // v has type @vec.Vec[Int]
  let a : Array[_] = [1, 2, 3]  // a has type Array[Int]
}
  • 报错信息中添加了错误代码,例如
./vec/sort.mbt:68:16-68:23 [E4021] The value identifier minimum is unbound.
./vec/sort_by.mbt:90:16-90:23 [E4021] The value identifier minimum is unbound.
./vec/vec.mbt:962:37-962:50 [E4020] Package "iter" not found in the loaded packages.
./vec/vec.mbt:963:3-963:13 [E4024] The type/trait @iter.Iter is not found.

IDE更新

  • 对构造器中的 labeled field 的 label 支持了 gotodef/gotoref/rename 等功能,例如 label.PNG

构建系统更新

  • 支持在 package 级别配置 warn list 与alert list
    • moon.pkg.json 中如下配置,可在编译时关闭对应的 warn 与 alter【其中 2alter_1alert_2 分别为编译器预设的 warn id (对于 Unused variable) 与用户自定义的 alert id】
{
  "warn_list": "-2",
  "alert_list": "-alert_1-alert_2"
}
  • -代表关闭对应 id 的 warn 与 alter,可用 moonc build-package -warn-help 查看预设的 warn

  • moon check|build|run|test 的默认后端由wasm切换为wasm-gc

  • moon test 默认执行模式由 release 修改为 debug

  • moon check|build|run|test支持自动安装依赖,而无需手动执行 moon install

  • moon doc --serve 支持指定地址与端口

-b, --bind <BIND> [default: 127.0.0.1]
-p, --port <PORT> [default: 3000]
  • 优化 moon 体积
平台优化前优化后
macOS arm647.3 MiB3.6 MiB
macOS x86_648.2 MiB4.1 MiB
Ubuntu x86_6414.0 MiB9.6 MiB
Windows x86_649.4 MiB4.9 MiB

工具链更新

  • moonrun 支持打印 backtrace, 使用样例: 使用 moon new hello 创建一个新项目,将 main/main.mbt 的内容替换为:
  fn bar() -> Unit {
  abort("")
}

fn foo() -> Unit {
  bar()
}

fn main {
  foo()
}

执行 moon run main --debug,可观察到输出类似:

error: RuntimeError: unreachable
    at $username/hello/main.bar.fn/1 (wasm://wasm/6fe99e5e:wasm-function[3]:0xe6)
    at $username/hello/main.foo.fn/2 (wasm://wasm/6fe99e5e:wasm-function[4]:0xea)
    at *init*/3 (wasm://wasm/6fe99e5e:wasm-function[5]:0xef)
    at <anonymous>:9:22

weekly 2024-04-30

· 阅读需 4 分钟

MoonBit 更新

  • 新增JavaScript后端

目前MoonBit已新增对JavaScript的支持并带来前所未有的性能提升,在JS后端实现了超出Json5近8倍性能的优势。更详细的介绍可以看一下这篇文章:IDEA研究院编程语言MoonBit发布JavaScript后端,速度提升25倍

如果你想自己体验一下,可以点击:https://github.com/moonbit-community/benchmark-202404/tree/master/bench_json5

  • 现在MoonBit允许传递回调函数至FFI。但回调函数的参数和返回值类型目前只能是简单类型,如Int等。例子:

    // 使用示例:传递回调函数至外部
    fn set_callback(f : () -> Int) = "ffi" "set_callback"
    
    // 使用示例
    fn use_callback() -> Int = "ffi" "use_callback"
    
    test {
      let i = { val : 0 }
      set_callback(fn () {
        i.val += 1
        i.val
      })
      inspect(use_callback(), content="1")?
      inspect(use_callback(), content="2")?
      inspect(use_callback(), content="3")?
      inspect(use_callback(), content="4")?
    }
    
    let f
    
    export default {
      // 必要外部接口:将闭包转换为JS函数。其他运行时根据语言不同实现方式不同
      'moonbit:ffi': {
        make_closure: (funcref, context) => funcref.bind(null, context)
      },
      // 使用示例
      ffi: {
        set_callback: (func) => {
          f = func
        }, // 设置回调函数
        use_callback: () => f() // 使用回调函数
      }
    }
  • 修改显式实现 trait(extension method)的语法,允许显式写出要给哪个类型实现 trait

    // 为 `Trait` 的方法 `method` 提供默认实现
    impl Trait with method(...) { ... }
    
    // 给类型 `Type` 实现 `Trait` 的方法 `method`
    impl Trait for Type with method(...) { ... }
    
    // 带类型参数的情况
    impl[X] Trait for Array[X] with method(...) { ... }
    

    和之前的 fn Trait::method(...) 语法相比,新的语法允许显式写出实现 trait 的类型,签名信息更丰富、更清晰。由于写出了类型,编译器可以自动推断出方法的参数和返回值类型,不需要手动标注:

    trait MyTrait {
      f(Self) -> Option[Int]
    }
    
    // 无需标注 `self` 和返回值的类型
    impl MyTrait for Int with f(self) {
      // 编译器能自动推断出返回值的类型是 `Option[Int]`
      Some(self)
    }
    
  • 支持Bytes字面量

    Bytes字面量b"..." 会将双引号内的ASCII字符串转换为Bytes类型,字符串内支持十六进制和八进制转义。

     let b1 : Bytes = b"ASCII"
     let b2 : Bytes = b"\xFF\o000"
    
  • { x } 的二义性问题修复

现在{ x }会解析成只有一个x字段的struct,相当于{ x: x }。对于这种容易造成混淆的写法,编译器会发出警告。

IDE更新

  • 插件新增moonbit.autoUpdate的选项控制是否开启自动更新的提示
  • 插件支持多后端开发
    • 用户可以在vscode里选择不同的后端
    • 非当前后端的代码对比度会变低

plugins.gif

构建系统更新

  • 支持后端特定文件,这些文件的拓展名以 .wasm|wasm-gc|js.mbt结尾,例如:foo.wasm.mbtfoo.wasm-gc.mbtfoo.js.mbt。例如在 moon build --target js 中,只有普通的 .mbt 文件与 .js.mbt 才会参与构建。相应地,moon check|build|test、以及moonbitlang/core的链接修改为与后端相关。

  • moon.pkg.json 中的 ["link"]["js"]中新增 format 字段,用于指定输出的JavaScript模块格式,可能的值为 esm|cjs|iife,默认为 esm

    • esm模式下,使用export { x as y }语句导出
    • cjs模式下,使用exports.y = x导出
    • iife模式下,使用globalThis.y = x导出

    moon.pkg.json样例:

    {
      "link": {
        "js": {
          "exports": [
            "hello"
          ],
          "format": "cjs"
        }
      }
    }
  • moon test -u支持自动更新测试块中的多个inspect函数,以及添加 -limit 选项用于限制自动更新的最大迭代次数。

工具链更新

  • moonrun由wasmtime切换到v8,现在支持wasm-gc后端
    moon new hello
    cd hello
    moon run main --target wasm-gc
  • moon info 的更新
    • 支持对方法进行分组,方便对比不同数据结构的实现
    • 支持带标签的参数、默认参数和自动填充参数
type Map
impl Map {
  debug_write[K : Debug, V : Debug](Self[K, V], Buffer) -> Unit
  elems[K, V](Self[K, V]) -> List[V]
  fold[K, V, T](Self[K, V], (T, V) -> T, ~init : T) -> T
  from_array[K : Compare + Eq, V](Array[Tuple[K, V]]) -> Self[K, V]
  // ...
}

weekly 2024-04-22

· 阅读需 4 分钟

MoonBit更新

  • 标准库里添加了 Iter 类型,该类型可以高效地对容器中的元素的进行访问,并且将访问过程优化成循环,使用方式比如:
test "iter" {
  let sum = Iter::[1, 2, 3, 4, 5, 6]
  .filter(fn { x => x % 2 == 1 })
  .take(2)
  .map(fn { x => x * x})
  .reduce(fn (x, y) { x + y }, 0)
  inspect(sum, content="10")?
}
  • 标准库里添加了VecView类型,可以使用如下方式对 Vec[T] 类型的值取它的 VecView[T]
test "view" {
  let v = Vec::[1, 2, 3, 4, 5]
  let vv1 = v[..]
  let vv2 = v[1..]
  let vv3 = v[..4]
  let vv4 = v[1..4]
  inspect(vv1, content="VecView::[1, 2, 3, 4, 5]")?
  inspect(vv2, content="VecView::[2, 3, 4, 5]")?
  inspect(vv3, content="VecView::[1, 2, 3, 4]")?
  inspect(vv4, content="VecView::[2, 3, 4]")?
}
  • array pattern支持 [a, .. as rest, b]形式,其中 rest 会绑定到一个VecView,例如:
test "view_pattern" {
    fn is_palindrome(s: VecView[Int]) -> Bool {
    match s {
      [] => true
      [_] => true
      [x, .. as rest, y] => x == y && is_palindrome(rest)
     }
    }
    let v1 = Vec::[1, 2, 3, 4, 5]
    @assertion.assert_false(is_palindrome(v1[..]))?
    let v2 = Vec::[1, 2, 3, 2, 1]
    @assertion.assert_true(is_palindrome(v2[..]))?
}
  • 标签参数调用时允许省略标签里的波浪线 ~,例如:
inspect(1, content="1")
  • 构造器支持带标签的参数:
pub enum Tree[X] {
  Nil
  Branch(X, ~left : Tree[X], ~right : Tree[X])
}

pub fn leftmost[X](self : Tree[X]) -> Option[X] {
  loop self {
    Nil => None
    // 使用 `label=pattern` 来匹配构造器的带标签参数
    Branch(top, left=Nil, right=Nil) => Some(top)
    // `label=label` 可以简写成 `~label`
    Branch(_, left=Nil, ~right) => continue right
    // 可以用 `..` 来忽略所有剩余的带标签参数
    Branch(_, ~left, ..) => continue left
  }
}

fn init {
  // 创建带标签的构造器的语法和调用带标签的函数一样
  let t: Tree[Int] = Branch(0, right=Nil, left=Branch(1, left=Nil, right=Nil))
  println(t.leftmost()) // `Some(1)`
}
  • 可选参数的默认值可以依赖前面的参数,例如:
fn f(~x: Int = 1, ~y: Int = x) -> Int {
  x + y
}
  • Byte字面量支持八进制转义。

Byte.PNG

IDE更新

  • IDE 支持本地环境的 test codelens;支持expect test的自动更新。

test-codelens.GIF

  • 修复在线 IDE 在 Windows 上找不到 core 的问题。

  • 支持识别 test_import*_test.mbt 文件。

工具链更新

  • moonfmt

    • 修复了StringChar字面量中的转义序列没有被正确格式化的问题;
    • 调整针对{ ..record }的格式化。
  • moon infomoon coverage 现已支持 Windows。

  • moon info 支持在不引起歧义时缩短类型名称,使得生成结果更加干净:

    • 在没有同名类型定义的时候隐藏 builtin 的包名前缀;
    • 在没有歧义时使用包名的最后一部分代替完整的包名。 更新前:
package moonbitlang/core/map

// -- snip --

type Map
fn Map::debug_write[K : @moonbitlang/core/builtin.Debug, V : @moonbitlang/core/builtin.Debug](Map[K, V], @moonbitlang/core/builtin.Buffer) -> Unit
fn Map::keys_set[K : @moonbitlang/core/builtin.Compare + @moonbitlang/core/builtin.Eq, V](Map[K, V]) -> @moonbitlang/core/immutable_set.ImmutableSet[K]
fn Map::lookup[K : @moonbitlang/core/builtin.Compare + @moonbitlang/core/builtin.Eq, V](Map[K, V], K) -> Option[V]
fn Map::to_vec[K, V](Map[K, V]) -> @moonbitlang/core/vec.Vec[Tuple[K, V]]

更新后:

package moonbitlang/core/map

alias @moonbitlang/core/immutable_set as @immutable_set
alias @moonbitlang/core/vec as @vec

// -- snip --

type Map
fn Map::debug_write[K : Debug, V : Debug](Map[K, V], Buffer) -> Unit
fn Map::keys_set[K : Compare + Eq, V](Map[K, V]) -> @immutable_set.ImmutableSet[K]
fn Map::lookup[K : Compare + Eq, V](Map[K, V], K) -> Option[V]
fn Map::to_vec[K, V](Map[K, V]) -> @vec.Vec[Tuple[K, V]]

构建系统更新

  • moon test 添加测试过滤相关选项:
-p, --package <PACKAGE_NAME>  Run test in the specified package
-f, --file <FILE>             Run test in the specified file, only valid when --package is specified
-i, --index <INDEX>           Run the index-nth test in the specified file, only valid when --file is specified

命令示例:moon test -p username/hello/A -f hello.mbt -i 0 (运行 username/hello/A 包中 hello.mbt 文件中的第 0 个 test block);-f-i 分别在指定 -p-f 时才有效;如果不指定 -f 则运行 -p 指定包中所有测试,不指定 -i 则运行 -f 指定文件中所有测试。

  • moon check|build|test 添加 --sort-input 选项,用于生成稳定的构建顺序。

  • expect test 生成的 ~content= 省略 ~,变更为 content=