方法调用只有第一个参数名为self才支持用 . 的语法是不是有点奇怪?


enum Expr {
  Cst(Int)
  Add(Expr, Expr)
  Mul(Expr, Expr)
  Sub(Expr, Expr)
  Div(Expr, Expr)
}

func exec(self : Expr) -> Int {
  match self {
    Cst(i) => i
    Add(l, r) => exec(l) + exec(r)
    Mul(l, r) => exec(l) * exec(r)
    Sub(l, r) => exec(l) - exec(r)
    Div(l, r) => exec(l) / exec(r)
  }
}

func init {
  let a1 = Expr::Add(Mul(Cst(1), Cst(2)), Cst(3))
  let a2 = Expr::Mul(Cst(10), Cst(20))
  let a3 = Expr::Mul(a1, a2)
  let a4 = Expr::Sub(a3, Add(Cst(20), Cst(30)))
  let a5 = Expr::Div(a4, Cst(10))
  a5.exec().print()
}


如题,一定要将参数名定义为self才能用.的语法,用起来感觉有点奇怪。

这里有提到。但是我觉得参数名只是一个提示作用。用self或者其他的命名不应该影响调用方式吧。

还有就是这里的enum 没有标记为recursive。moonbit中enum是什么样的内存布局呢?采用链表吗?这样是不是对非递归的enum有性能的问题呢?

1 个赞

方法和普通函数的区别主要在命名空间上。同一个名字的普通函数只能有一个,而不同的类型可以有同名的方法。比如:

func f(x: Int) { ... }
// 不能再定义 func f(x: String) { ... } 了

// 下面的没有问题
func f(self: Int) { ... }
func f(self: String) { ... }
func init {
  1.f()
  "1".f()
}

因为用 . 调用时,有类型信息来帮助选择调用哪个方法。Moonbit 目前是用第一个参数的名字来区分方法和普通函数的:第一个函数叫作 self 就是方法,否则就是函数。但如果这个语法有什么不好的地方或者有其他更好的语法的话欢迎提出。

enum 这件事上,递归的 enum 会自动 box,不需要手动裹指针。所以写类型定义的时候也可以直接写,不用考虑要不要 box,有没有递归的问题。Moonbit 的定位不是特别底层的语言,所以类型的内存布局会让编译器去内部优化,而不是暴露给用户。

3 个赞