文档#

文档注释#

文档注释是在顶层结构(如 fnletenumstructtype)的每一行前面加上 /// 的注释。文档注释内包含 markdown 文本。

/// 返回一个新数组,其中元素被反转。
fn[T] reverse(xs : Array[T]) -> Array[T] {
  ...
}

文档注释中的 markdown 代码块会被视作文档测试,moon checkmoon test 会自动检查并运行这些测试,这能保证文档注释中的代码示例永远不会过时。MoonBit 会自动给在文档注释的内容周围裹上一层 test 块,所以编写文档测试时无需手动包裹 test { .. } 块:

/// Increment an integer by one,
///
/// Example:
/// ```
/// inspect(incr(41), content="42")
/// ```
pub fn incr(x : Int) -> Int {
  x + 1
}

如果想要阻止一段代码被当作文档测试,只需要在它的 markdown 代码块上标记一个 mbt 以外的语言名字:

/// `c_incr(x)` 等价于下面的 C 代码:
/// ```c
/// x++
/// ```
pub fn c_incr(x : Ref[Int]) -> Int {
  let old = x.val
  x.val += 1
  old
}

目前,文档测试都是 黑盒测试。所以私有定义目前不能有文档测试。

属性#

属性是放置在顶层成员之前的标注。它们都采用 #attribute(...) 的形式。一个属性标注占用整行的空间,其中不允许换行。属性一般不会影响程序的含义。无用的属性标注将会触发警告。

“弃用”属性#

#deprecated属性用于标记一个函数、类型或者特征为弃用状态。当弃用的成员在其他包中被使用时,MoonBit 将会触发警告。你可以传递一个字符串参数给这个属性,来自定义警告中显示的消息。

例如:

#deprecated
pub fn foo() -> Unit {
  ...
}

#deprecated("使用Bar2代替")
pub enum Bar {
  Ctor1
  Ctor2
}

“可见性”属性#

备注

这里的文档不涉及访问控制。关于如何使用pubpub(all)priv, 见 访问控制.

#visibility属性和#deprecated属性类似。但它用于提示用户一个类型未来将改变它的可见性。对于外部的包,如果使用这个类型的方式在未来改变可见性以后不再合法,它将会触发警告。

// 在包 @util 中
#visibility(change_to="readonly", "Point将会变成只读的类型")
pub(all) struct Point {
  x : Int
  y : Int
}

#visibility(change_to="abstract", "使用 new_text 和 new_binary 代替")
pub(all) enum Resource {
  Text(String)
  Binary(Bytes)
}

pub fn new_text(str : String) -> Resource {
  ...
}

pub fn new_binary(bytes : Bytes) -> Resource {
  ...
}

// 在另一个包中
fn main {
  let p = Point::{ x: 1, y: 2 } // 触发警告 
  let { x, y } = p // ok
  println(p.x) // ok
  match Resource::Text("") { // 触发警告
    Text(s) => ... // 触发警告
    Binary(b) => ... // 触发警告
  }
}

#visibility属性接受两个参数:change_tomessage

  • change_to参数是一个表示该类型新的可见性的字符串,它可以是"abstract"或者"readonly"

    "change_to"的值

    将要禁止的使用

    "readonly"

    创建该类型的实例,或者变更实例的字段的值。

    "abstract"

    创建该类型的实例、变更实例的字段的值、对它的实例进行模式匹配或者访问实例的字段。

  • message参数用于提供额外的信息,告诉使用者关于可见性的变更。

“内部”属性#

#internal属性用于标记一个函数、类型或者特征为内部的。所有在模块外的使用将会触发警告。

#internal(unsafe, "这是个不安全的函数")
fn unsafe_get[A](arr : Array[A]) -> A {
  ...
}

“内部”属性接受两个参数:categorymessagecategory 是一个标识符,表示警示对应的类别。message 是一个字符串,表示警示中额外的提示信息。

警示可以通过配置moon.pkg.json中的alert-list选项来关闭。关于更多的细节,见 警示列表.

外部属性#

#external属性用于标记一个抽象类型为外部类型。

  • 对于 Wasm(GC) 后端,它将被解释为anyref

  • 对于 JavaScript 后端,它将被解释为any

  • 对于原生后端,它将被解释为void*

#external
type Ptr

Borrow 和 Owned 属性#

#borrow#owned 属性用于表示一个外部接口是否获得参数的所有权。对于更多细节,见 FFI

As Free Function 属性#

#as_free_fn 属性用于标记一个方法,同时它也被声明为一个自由函数。它还可以改变自由函数的可见性、自由函数的名字,并且提供单独的弃用警告。

#as_free_fn(dec, visibility="pub", deprecated="use `Int::decrement` instead")
#as_free_fn(visibility="pub")
fn Int::decrement(i : Self) -> Self {
  i - 1
}

test {
  let _ = decrement(10)
  let _ = (10).decrement()
}

调用位置属性#

#callsite 属性用于标记发生在调用位置的属性。

它可以是 autofill,用于在调用位置自动填充参数 SourceLoc 和 ArgLoc

它也可以用于迁移,帮助下游用户适应新的调用约定:

#callsite(migration(y, fill=true, msg="must fill y for migration"), migration(z, fill=false, msg="cannot fill z for migration"))
fn f(x~ : Int, y? : Int = 42, z? : Int) -> Unit {
  ...
}

跳过属性#

#skip 属性用于跳过一个测试块。类型检查仍然会被执行。

配置属性#

#cfg 属性用于执行条件编译。例子有:

#cfg(true)
#cfg(false)
#cfg(target="wasm")
#cfg(not(target="wasm"))
#cfg(all(target="wasm", true))
#cfg(any(target="wasm", target="native"))