跳到主要内容

weekly-04-01

· 阅读需 5 分钟

MoonBit 更新

1. expect 测试添加 inspect 函数

expect 测试添加针对 Show 接口的 inspect 函数,签名如下:

pub fn inspect(
obj: Show,
~content: String = "",
~loc: SourceLoc = _,
~args_loc: ArgsLoc = _
) -> Result[Unit, String]

⚠️ 此API暂不稳定,在未来可能会更改为 expect 函数

使用 inspect 可以更方便编写测试,例如对于如下代码:

fn add(x: Int, y: Int) -> Int {
x + y
}

test {
inspect(add(1, 2))?
}

test {
(add(3, 4) |> inspect)?
}

执行 moon test -u 之后,文件被自动更新为:

fn add(x: Int, y: Int) -> Int {
x + y
}

test {
inspect(add(1, 2), ~content="3")?
}

test {
(add(3, 4) |> inspect(~content="7"))?
}

2.编译器内置函数迁移到标准库

把原本的在编译器内部的一些基础的 MoonBit 定义迁移到了标准库中。在线IDE上也可以使用标准库了

3. 支持 alert pragam

MoonBit 现在支持在顶层的文档注释中书写多个 pragam。所有的 pragam 以@开头,并且独占一行。

Untitled

目前支持函数和方法的 alert pragma,当被标记了 alert 的函数和方法被使用时会产生警告。这个机制可以用来标记已经弃用或者不安全的函数。alert pragma 的格式为@alert id "explain string",其中id可以是任意的标识符。

Untitled

4. 支持在 pragma 中标注 intrinsic

比如标准库中的如下代码在被标注 intrinsic 之后,在 JavaScript 后端会使用 String(..) 函数来将浮点数转化为字符串,后续会加入更多函数的 intrinsic 支持。

/// @intrinsic %f64.to_string
pub fn to_string(self : Double) -> String {
double_to_string(self)
}

5. 生成代码性能和体积的改进

  • 引入了消除局部 alias 的优化,从而避免生成无用的局部变量
  • 引入了常量传播的优化
  • 优化了生成的 wasm 代码中类型声明的部分,减少了冗余的类型声明

https://picx.zhimg.com/80/v2-18712f8e289e2548fdafcd3775aa060e_1440w.jpg?source=d16d100b

6. moonfmt 改进

  • 调整 function for loop 的打印格式,特殊情况不再打印分号
  • 针对 if/match 这种可读性差的嵌套的情况,格式化后加上额外的括号。格式化前和格式化后的效果:

格式化前:

Untitled

格式化后:

Untitled

7. 改进模式匹配完备性检查

8. 调整字符串的编码为UTF-16

构建系统更新

moon.pkg.json 中支持自定义函数导出名称

moon.pkg.json 中支持使用 ["link"][BACKEND]["exports] 字段自定义函数导出名称,并且默认不再导出所有的 pub 函数,必须要在 exports 中显式指定。此外,现在支持通过设置 link 字段链接非 main 包。

例如使用 moon new hello 创建一个新项目,其目录结构为:

.
├── README.md
├── lib
│ ├── hello.mbt
│ ├── hello_test.mbt
│ └── moon.pkg.json
├── main
│ ├── main.mbt
│ └── moon.pkg.json
└── moon.mod.json

在过去,执行 moon build,只有 main 包会生成 wasm 文件。

现在,在 moon.pkg.json 中支持 link 字段,可以对非 main 包生成 wasm 文件。link 字段的内容可以是一个布尔值:

{
"link": true // 表示当前包需要被链接
}

或者是一个对象,可以给不同的后端如 wasm 或者 wasm-gc ,设定链接选项。目前只支持 exports 选项,exports 是一个字符串数组,包含需要导出的函数及其需要导出的名称:

{
"link": {
"wasm": {
"exports": [
"hello" // 这里将函数 hello 导出为 hello,
]
},
"wasm-gc": {
"exports": [
"hello:hello_wasm_gc" // 这里将函数 hello 导出为 hello_wasm_gc
]
}
}
}

如果将 lib/moon.pkg.json 中的内容修改为:

{
"link": {
"wasm": {
"exports": [
"hello"
]
}
}
}

然后执行 moon build --output-wat,可以观察到输出的 target/wasm/release/build/lib/lib.wat 中包含如下内容:

(func $$username/hello/lib.hello.fn/1 (export "hello") (result i32)
(i32.const 10000))

其中的 (export "hello") 表示配置生效了。

IDE 更新

vscode 插件支持安装或更新 MoonBit工具链。

Untitled

weekly-03-25

· 阅读需 3 分钟

构建系统更新

1. 支持 expect testing

a. 使用 moon new 新建一个 MoonBit 项目。

b. 在 lib/hello.mbt中写入:

pub fn hello() -> String {
"Hello, world!"
}

test {
let buf = Buffer::make(10)
buf.write_string(hello())
buf.expect()?
}

c. 然后运行 moon test --update或者 moon test -u:

$ moon test --update
expect test failed at lib/hello.mbt:8:3-8:15
Diff:
----
Hello, world!
----

Total tests: 1, passed: 0, failed: 1.

Auto updating expect tests and retesting ...

Total tests: 1, passed: 1, failed: 0.

d. 再次打开 lib/hello.mbt 文件,可以看到已经将测试结果 promote 到源码中。

pub fn hello() -> String {
"Hello, world!"
}

test {
let buf = Buffer::make(10)
buf.write_string(hello())
buf.expect(~content="Hello, world!")?
// ^~~~~~~~~~~~~~~~~~~~~~~~ 测试结果更新
}

2. moon run 不再支持 --output-wat选项。

MoonBit 更新

1. 支持多参数构造器的后端代码生成

支持多参数构造器(multi-argument constructor)的后端代码生成。现在构造一个泛型类型的值的时候,如果泛型参数为元组的话必须要写括号,即:

enum A[X] {
A(X)
}

fn init {
// Error, expecting 1 arg, getting 2
A::A(1, 2) |> ignore

// Ok
A::A((1, 2)) |> ignore
}

多参数构造器 unbox 了参数,能够提高生成的代码的性能,也允许程序员对数据的内存布局有了更多的掌控。

2. 调整了Int64的lsl, lsr, asr方法

现在移位参数不再是Int64,而是Int。同时调整了clz, ctz, popcnt方法,现在返回类型不再是Int64,而是Int。此项改变有助于我们在不支持原生Int64的平台上生成更高效的代码。

IDE 更新

1. 支持带标签参数的重命名。

2. VSCode 插件支持自动安装或者更新 MoonBit

a. 更新插件后,如果没有安装 moon 或者 moon 不是最新的时候,VSCode 右下角弹出自动安装/升级的提示。

Untitled

b. 点击 "yes", 来执行自动安装任务。任务完成后就可以用了。

Untitled

weekly-03-18

· 阅读需 3 分钟

语言更新

1. 实验性地添加对 trait 实现默认方法的功能

trait MyShow {
repr(Self) -> String
str (Self) -> String // it has a default implementation
}

impl MyShow::str(self : Self) -> String {
// default implementation of str
self.repr()
}

type MyInt Int
fn repr(self:MyInt) -> String {
self.0.to_string()
}
// Now MyInt implements MyShow now

2. 允许类型定义的类型参数为 _

_可以用来定义 phantom type,来限制一些程序逻辑上非法的操作。例如我们希望不同单位的长度不能够相加:

type Length[_] Int

type Kilometer
type Mile

fn add[T](x: Length[T], y:Length[T]) -> Length[T] {
Length::Length(x.0 + y.0)
}

let d_km: Length[Kilometer] = Length(10)
let d_mile: Length[Mile] = Length(16)

此时,两个单位不同的长度并不能够直接相加:

fn init {
add(d_km, d_mile) |> ignore
// ^~~~~~ Error: Expr Type Mismatch
}

而两个单位相同的长度可以相加:

fn init {
add(d_km, d_km) |> ignore
// OK
}

3. 现在 Toplevel 函数没有标记返回值的行为改成报错

Toplevel 函数没有标记返回值的行为从之前的默认设置为 Unit 改成报错。

fn print_hello() {
// ^~~~~~~~~~~ Error:
// Missing type annotation for the return value.
println("Hello!")
}

4. 添加了按位取反的操作符

fn main {
println((1).lnot())
}

输出:

-2

5. 改进 List::to_string/debug_write 的输出

fn main {
let l = List::Cons(1, Cons(2, Cons(3, Nil)))
println(l)
}

输出:

List::[1, 2, 3]

6. 添加了 Byte 类型

byte 字面量由 b 作为前缀,使用方式如下:

fn init {
let b1 = b'a'
println(b1.to_int())
let b2 = b'\xff'
println(b2.to_int())
}

更多关于 Byte 的功能还在完善中

IDE更新

1.支持对 moonbitlang/core 的补全

2. 格式化的更新和修复:

  • 调整空的 struct、enum、trait,避免出现空行。

之前:

struct A {

}

之后:

struct A {}
  • 修复 continue 的错误缩进。
  • 修复多行语句格式化后出现分号的问题。

构建系统更新

1. moon.mod.json 添加了 test_import 字段

test_import这个字段中用到的依赖只会在测试的时候被用到。

2. 优化 moon test 输出

默认只输出失败的测试用例信息,如果需要完整输出可使用moon test -v命令。

weekly-03-11

· 阅读需 6 分钟

01 MoonBit 更新

1. moonbitlang/core 开源

moonbitlang/core(MoonBit标准库)现已开源。我们很高兴收到社区的积极反馈,想了解更多与moonbitlang/core开源的详情,可点击这里查看:国人自主研发的编程语言 MoonBit Core 开源啦!

Github链接:

https://github.com/moonbitlang/core

2. 支持带标签/可选参数

支持带标签参数(labelled argument)和可选参数(optional argument)。带标签参数有助于区分相同类型,不同功能的函数:

fn greeting(~name: String, ~location: String) {
println("Hi, \\(name) from \\(location)!")
}

fn init {
greeting(~name="somebody", ~location="some city")
let name = "someone else"
let location = "another city"
greeting(~name, ~location)// `~label=label` 可以简写成 `~label`
}

可选参数必须带标签,并且指定默认值。在函数调用的时候,如果没有手动指定参数,则取默认值。注意:默认值在每次调用的时候都会被重新求值:

fn greeting(~name: String, ~location: Option[String] = None) {
match location {
Some(location) => println("Hi, \\(name)!")
None => println("Hi, \\(name) from \\(location)!")
}
}

fn init {
greeting(~name="A")// Hi, A!
greeting(~name="B", ~location=Some("X")// Hi, B from X!
}

3. 提供了内建类型 SourceLoc

SourceLoc,表示源码中的位置。假如某个函数声明了一个类型为 SourceLoc、默认值为 _ 的可选参数,那么每次调用这个函数时,MoonBit 会自动插入调用处的位置作为这个参数的默认值:

fn f(~loc : SourceLoc = _) {
println("called at \\(loc)")
}

fn g(~loc : SourceLoc = _) {
f()// 显示 `g` 内部的位置
f(~loc)// 自动注入的参数也可以手动覆盖。这一次调用会显示 `g` 的调用者的位置
}

test "source loc" {
g()
}

try.moonbitlang.cn 新建一个名为 test.mbt 的文件,放入上述代码,并运行代码中的测试,可以得到如下的输出:

test source loc ...
called at memfs:/sample-folder/test.mbt:6:3-6:6
called at memfs:/sample-folder/test.mbt:11:3-11:6

SourceLoc 可以用于编写测试相关的函数,用于在测试失败时输出有用的位置信息:

fn assert_eq[X: Eq + Show](result: X, expect: X, ~loc : SourceLoc = _) -> Result[Unit, String] {
if (result == expect) {
Ok(())
} else {
Err("\\(loc): Assertion failed: \\(result) != \\(expect)")
}
}

test "1 =? 2" {
assert_eq(1, 2)?
}
running 1 tests
test 1 =? 2 ... FAILED memfs:/sample-folder/test.mbt:10:3-10:18: Assertion failed: 1 != 2

test result: 0 passed; 1 failed

4. === 已经弃用,可以使用 physical_equal 作为代替

5. 添加新的内置类型 UnsafeMaybeUninit[T]

添加新的内置类型 UnsafeMaybeUninit[T] 和对于该类型的一些相关操作,用以在 MoonBit Core 中实现 Vector 等数据结构,因为其不安全性,普通的 MoonBit 程序中应尽可能避免使用该类型。

02构建系统更新

1. 支持 JavaScript 后端

可以通过 --target js 来生成后端代码。例如:

a. 通过 moon new hello 新建一个名为 hello 的项目

b. 在 main/main.mbt 中写入:

fn main {
println("Hello from JavaScript!")
}

c. 在命令行中构建生成 JavaScript 代码,并使用 Node 运行。

$ moon build --target js
moon: ran 2 tasks, now up to date
$ node target/js/release/build/main/main.js
Hello from JavaScript!

d. 你也可以方便地通过 moon run main --target js 来编译并运行编译到 JavaScript 的 MoonBit 代码。

$ moon run main --target js
Hello from JavaScript!

2. 修复了一些 moonbuild 的问题

a. 修复了 Windows 上 moon upgrade 失败的问题。

b. 修复了 moon add 添加新版本没有移除旧版本的问题。

c. 修复了本地 moon check 失败仍然能够 publish 的问题。

IDE更新

1. 线上 IDE 支持通过 CodeLens 的方式运行测试

ide更新|306x168

2. 大幅度改善 moonfmt 的对于包含注释的源代码的处理。

3. 提升 IDE 和 VSCode 插件的稳定性和用户体验

a. VSCode插件现在是在文件更改的时候调用moon check而非启动moon check -w

b. 提升了多行字符串和文档注释(docstring)的输入体验。现在在多行字符串/文档注释内部换行会自动补上 #| 或者 /// 的前缀。

c. 修复了 hover、moon.pkg.json 出错,空文件等导致 lsp 报错的问题。

工具链更新

Markdown linter 支持 expr 标签

举个例子:

```moonbit expr
1 * 2 + 3

可以在运行 mdlint 的时候看到对应的输出:

5

weekly-03-04

· 阅读需 5 分钟

一、MoonBit更新

1. 添加了 += 系列语句

包括+=、-=、*=、/=,支持运算符重载:

fn init {
let array = [1,2,3,4]
array[2] *= 10
println(array) // [1, 2, 30, 4]
}

fn init {
let mut a = 1
a += 20
println(a) // 21
}
struct Foo {
data : Array[Int]
} derive(Debug)

fn op_set(self : Foo, index : Int, value : Int) {
self.data[index] = value
}

fn op_get(self : Foo, index : Int) -> Int {
self.data[index]
}

fn init {
let foo : Foo = { data: [0,0,0,0] }
foo[2] -= 10
debug(foo) // {data: [0, 0, -10, 0]}
}

2. 现在 toplevel 如果没有顶格会报错

如下图所示:

image|690x204

3. 引入 super-trait 机制

Super-trait 通过如下的语法指定:

trait A {
// ...
}

trait B : A { // A is a super trait of B, B is a sub trait of A
// ...
}

可以通过 + 来指定多个 Super-trait,表示该 sub-trait 依赖这几个 super-trait:

// ...

trait B: A + Compare + Debug {
// ^~~ B is a sub-trait of A *and* Compare *and* Debug
// ...
}

在使用上,可以将 sub-trait 当作 super trait 使用,但是不能够将 super-trait 当作 sub-trait 使用。目前Compare是Eq的 sub-trait,意味着实现了Compare的类型能够在要求Eq的情况下使用,所以以这两个代码为例:

trait Eq {
op_equal(Self, Self) -> Bool
}

trait Compare: Eq {
compare(Self, Self) -> Int
}

fn eq[X: Compare](this: X, that: X) -> Bool {
this == that
}
fn compare[X: Eq](this: X, that: X) -> Int {
this.compare(that)
// ^~~~~~~ Type X has no method compare.
}

4. 添加T::[x, y, ...]的语法

这种语法结构会被解糖成T::from_array([x, y, ...])的形式。这种语法使得列表等线性数据结构的初始化更加易读。

enum List[X] {
Nil
Cons(X, List[X])
} derive(Show, Debug)

fn List::from_array[X](array: Array[X]) -> List[X] {
let mut list = List::Nil
for i = array.length() - 1; i >= 0; i = i - 1 {
list = Cons(array[i], list)
}
list
}

fn main {
println(List::[1, 2, 3])
}

输出:

Cons(1, Cons(2, Cons(3, Nil)))

5. 调整自动生成的 Show 的实现的逻辑

现在它会调用 Debug 作为实现。这意味着,现在 derive(Show) 之前需要先 derive 或自行实现 Debug。Debug 的输出是 MoonBit 语法下合法的值,而 Show 可以用于输出更美观的内容。这修复了之前 derive(Show) 在有 String 的结构体上的错误行为:

struct T {
x: String
} derive(Show, Debug)

fn init {
println({ x: "1, y: 2" })
// 之前: {x: 1, y: 2}
// 现在: {x: "1, y: 2"}
}

6. 目前已不支持fn hello() = "xx"的语法

fn hello() = "xx"的语法目前已经不适用了。我们建议用户这样写:

extern "wasm" fn hello () =
#| ...

现在 inline stubs 只支持 wasmgc,不支持 wasm1。

7. 现在丢弃非 Unit 的值会直接报错,如果需要丢弃需要显式使用 ignore。

fn f() -> Int {
ignore(3) // Ok.
3 |> ignore // Ok.
3 // Err: Expr Type Mismatch: has type Int, wanted Unit
3 // Ok, as this value is returned, not dropped
}

8. 移除了test作为标识符使用的支持

二、IDE更新

1. 提供更好的线上 IDE Markdown 支持

  • 可以在线上 IDE 中使用 Marp 插件来查看之前现代编程思想课的内容了。

image|690x481

  • Markdown 中内嵌的 MoonBit 的代码块支持语法高亮。

image|690x475

  • 针对内嵌有 MoonBit 代码的 Markdown 文本开发了语法检查的程序,开源在:GitHub链接。使用方法可以参考项目的 README。

三、构建系统更新

1. 添加 main 函数的支持

  • main只能写在main包(is_main: true的包)里
  • main 包中应当有且仅有一个main 函数
  • main函数的执行顺序在所有init函数之后
  • main包中不能有test

2. 目前可以通过 moon upgrade 升级 MoonBit 工具链的版本了。

p.s. 但是在使用之前,必须再用安装脚本安装一次:-)

3. moon check|build|run 现在默认链接到 moonbitlang/core。

weekly-02-26

· 阅读需 4 分钟

MoonBit 更新

1. 支持云原生调试功能

现在,你可以通过访问 try.moonbitlang.cn,直接在浏览器中使用 devtools 调试 MoonBit 程序,无需安装任何软件。具体的使用步骤如下:

2. MoonBit 支持使用 for 关键字定义的函数式循环控制流

MoonBit 现在支持使用 for 关键字定义的函数式循环控制流,其性能接近于 C/C++ 等底层语言,比如 fib 函数可以写成如下形式:

fn fib( n : Int ) -> Int {
for i = 0, a = 1, b = 2
i < n
i = i + 1, a = b, b = a + b {
} else { b }
}

MoonBit 的 for 循环可以作为表达式返回一个值,比如上述程序中在循环结束后使用 b 作为整个 for 循环的值,也可以在 for 的循环体中通过 break 提前返回,比如:

fn exists(haystack: Array[Int], needle: Int) -> Bool {
for i = 0; i < haystack.length(); i = i + 1 {
if haystack[i] == needle {
break true
}
} else {
false
}
}

此外,在 for 循环中可以像传统语言一样使用 continue 进入下一次循环,MoonBit 额外提供了带参数的 continue 来指定下一次循环过程中循环变量的值,比如:

fn find_in_sorted[T](xs: Array[(Int, T)], i: Int) -> Option[T] {
for l = 0, r = xs.length() - 1; l < r; {
let mid = (l + r) / 2
let k = xs[mid].0
if k == i {
break Some(xs[mid].1)
} else if k > i {
continue l, mid
} else {
continue mid + 1, r
}
} else {
None
}
}

在不需要返回值的情况下,else 分支可以省略,比如:

fn print_from_0_to(n: Int) {
for i = 0; i <= n; i = i + 1 {
println(i)
}
}

3. Inline test 改进

测试的返回类型从Unit改成了Result[Unit,String],用于表示测试的结果:

 test "id" {
if (id(10) != 10) { return Err("The implementation of `id` is incorrect.") }
}

编译器会自动将test "id" {...} 的语句块{...}使用Ok()包裹起来。因此,当语句块的类型为Unit并且没有提前return时,表示inline test测试通过。配合问号操作符,可以让测试变得更加优雅:

fn id(x : Int) -> Int {
x + 1 // incorrect result
}

fn assert(x : Bool, failReason : String) -> Result[Unit,String] {
if x { Ok(()) } else { Err(failReason) }
}

test "id" {
assert(id(10) == 10, "The implementation of `id` is incorrect.")?
}

执行moon test,输出如下:

➜  my-project moon test
running 1 tests in package username/hello/lib
test username/hello/lib::hello ... ok

test result: 1 passed; 0 failed

running 1 tests in package username/hello/main
test username/hello/main::id ... FAILED: The implementation of `id` is incorrect.

test result: 0 passed; 1 failed

Hello, world!

4. 改进 VS Code 插件的函数签名提示,现在会显示参数名:

5. 改进了 VS Code 插件对 core 包开发的支持

6. moon new 支持快速创建新项目

  • moon new hello 在文件夹 hello 中创建一个名为 username/hello 的可执行项目
  • moon new hello --lib 在文件夹 hello 中创建一个名为 username/hello 的模块

weekly-02-19

· 阅读需 3 分钟

MoonBit更新

1. 增加了functional for loop控制流支持

与传统的命令式for loop 不同,循环变量是不可变的。这样的设计将来也容易抽取出来做形式化验证:

fn init {
for i = 0; i < 5; i = i + 1 {
debug(i)
// i = i + 4 error: The variable i is not mutable.
}
}

输出:

01234

functional for loop也支持多个绑定。与其他语言不同的是,x和y在functional for loop的第三个表达式里具有同时更新的语义:

fn init {
for x = 0, y = 0; x < 10; x = x + 1, y = x + 1 {
// ^~~ 这里x的值是更新前的
println("x: \(x), y: \(y)")
}
}

输出:

x: 0, y: 0
x: 1, y: 1
x: 2, y: 2
x: 3, y: 3
x: 4, y: 4
x: 5, y: 5
x: 6, y: 6
x: 7, y: 7
x: 8, y: 8
x: 9, y: 9

functional for loop内部也支持使用breakcontinue

fn init {
let xs = [0,1,2,3,4,5,6,7,8]
let mut sum = 0
for i = 0, v = xs[0]; i < xs.length(); i = i + 1, v = xs[i + 1] {
if v % 2 == 0 { continue }
if v >= 7 { break }
sum = sum + v
}
debug(sum) //output: 9
}

2. 改进moon new创建项目的向导

现在可以用方向键选择创建lib或者exec项目:

3. IDE支持管道运算符的智能补全

对于第一个参数类型与管道左侧表达式类型相等的函数,会放在补全列表的顶部,其它的补全选项仍然会显示在列表后。

4. 根据社区反馈调整了pipe表达式

现在管道运算符右侧支持Double::to_int这样的函数调用。

fn init {
debug(3.14 |> Double::to_int) // output: 3
debug(4 |> Array::make('c')) // output: ['c', 'c', 'c', 'c']
}

5. 修复IDE中缀表达式错误地插入inlay hint的问题

weekly-02-05

· 阅读需 2 分钟

MoonBit 更新

1. 新增多行字符串支持

每行需要以#|开头。多行字符串每行之间允许断开、插入注释,字符串内不支持转义和字符串插值。

2. 新增函数式的loop循环

其中continue 只允许出现在尾递归调用的位置,loop内允许使用break提前返回一个值。

3. 提供Trait::method调用支持

支持以Debug::debug_write(self, buf)的形式调用trait method

4. 添加实验性标准库机制

最新的安装脚本会将标准库下载到 ~/.moon/lib/core 目录下。目前标准库的内容以及相关IDE支持暂不稳定,因此构建系统默认不链接标准库。对于想要提前体验标准库功能的开发者们,可以在 moon check|build|run|test 命令后添加 --std 选项用于链接标准库到当前项目。

5. 支持隐式到trait object的转换

在上下文中明确需要一个trait object时,会自动插入 as SomeTrait。例如下面的代码:

现在我们可以省略as Debug

6. 支持函数参数的inlay hint

7. 字符串和char字面量支持unicode转义、十六进制转义和八进制转义

weekly-01-29

· 阅读需 2 分钟

MoonBit更新

1. 新增特性Trait object:

能够显式地将类型不同但实现相同trait的值装箱并表示成同一个类型,实现函数的动态分发。

fn get_show_list() -> List[Show] {
let a = 42 as Show
let b = "xxx" as Show
let c = 3.14 as Show
List::Cons(a, Cons(b, Cons(c, Nil)))
}

fn init {
fn print_show_list {
List::Cons(a, rest) => { println(a); print_show_list(rest) }
List::Nil => ()
}
print_show_list(get_show_list())
}

2. 新增管道运算符

提供类似于链式调用的语法,可以串联多个连续的函数调用,省去let name = ...的代码。例如value |> func1(arg1,arg2) |> func2 相当于:

let a = value
let b = func1(a, arg1, arg2)
func2(b)

另一个例子:

fn sub2(x : Int, y : Int) -> Int {
x - y
}

fn sum3(x : Int, y : Int, z : Int) -> Int {
x + y + z
}

fn init {
6 |> sub2(5) |> sum3(1,2) |> println()
}

3. 字符串支持使用\xFF进行十六进制转义

fn init {
let data = "\x48\x65\x6c\x6c\x6f"
println(data) //output: Hello
}

4. Inline test变更

现在test mode也会执行fn init,执行顺序在inline test之前。 |690x498

5. Moonfmt:改进类型和长数组字面量的缩进

原代码:

改进前的格式化效果:

改进后的格式化效果:

weekly-01-22

· 阅读需 3 分钟

MoonBit更新

1. 新增矩阵函数的语法糖

新增矩阵函数的语法糖,用于方便地定义局部函数和具有模式匹配的匿名函数:

fn init {
fn boolean_or { // 带有模式匹配的局部函数
true, _ => true
_, true => true
_, _ => false
}
fn apply(f, x) {
f(x)
}
let _ = apply(fn { x => x + 1 }, 42) // 匿名函数
let _ = apply(fn { // 带有模式匹配的匿名函数
0 => 0
1 => 1
_ => 2
}, 42)
}

2. 新增使用 T::{ ... }构造结构体的语法

这个新语法可用于显式的指定结构体的类型,并会使得结构体内有更好的补全:

struct T {
x: Int
y: Int
}

struct T2 {
x: Int
y: Int
}

fn init {
let x = T::{x: 1, y: 2}
debug(x.x + x.y) // 3
}

3. 正式移除 var id = expr 的语法

4. 增加了新的关键词 test

新的测试语法 test "name" {},用于代替原先的fn test_name(){}。目前暂时只有顶格缩进的test会被识别成关键字,未来将不再支持使用test作为标识符。 旧语法: fn test_ name {} 新语法: test " name " {}

5. 支持在 init 或者 test 代码块中使用 return 语句

fn init  {
if i > 0 {
return
}
...
}

test {
if i > 0 {
return
}
...
}

插件更新

改进了语法高亮:

Before:

After:

mooncakes.io 更新

1. 新增 mooncakes.io 注册方式

现在mooncakes.io 支持使用用户名+邮箱方式注册,而不仅限于之前的GitHub登录方式。现在新用户可以抢先注册你心仪的用户名。(注意:用户名字符需要>=5,如果小于5需要联系管理员后台操作。)

$ moon register
Choose a way to register: Email
You chose: Email
Username: xxxxxx
Password: [hidden]
Email: xxxxxx@xxx.xx
Send verification code to your email[bzy_sustech@foxmail.com]? yes
Please input the verification code: xxxxxx
Register successfully!
API token saved in ~/.moon/credentials.json

2. 增加跳转到源代码的功能