Scala表达式之间的区别

时间:2018-03-14 03:16:28

标签: scala scala-meta

直到最近,我的理解是下面的两个Scala语句是可以互换的。

expr.op(arg1, arg2,...)
expr op (arg1, arg2,...)

但是我一直在玩scala meta,看着他们产生的AST,

Term.Apply(Term.Select(<exprTerm>, Term.Name("op")), Seq(<argTerm1>, <argTerm2>,...))
Term.ApplyInfix(<exprTerm>, Term.Name("op"), Nil, Seq(<argTerm1>, <argTerm2>,...))

并在AST中找到了中缀表达式的Nil。进一步深入研究,我发现中缀选项允许输入类型参数:

expr op [Type1, Type2,...] (arg1, arg2,...)

在这种情况下,我不明白他们的目的是什么。什么时候它们会有用?为什么他们允许进行中缀操作但不允许&#34; apply-select&#34;操作(expr.op(arg1, arg2,...))?

1 个答案:

答案 0 :(得分:3)

这些类型不是参数类型,而是泛型。例如:

object expr {
  def op1(param1: Any, param2: Any) = ()
  def op2[T](param1: Any, param2: Any) = ()
}

我们会得到

expr op1 (1, 2)
// Term.ApplyInfix(Term.Name("expr"), Term.Name("op1"), Nil, List(Lit.Int(1), Lit.Int(2)))
expr op2[Int] (1, 2)
// Term.ApplyInfix(Term.Name("expr"), Term.Name("op2"), List(Type.Name("Int")), List(Lit.Int(1), Lit.Int(2)))

后缀变种:

expr.op1[Int](1, 2)
//Term.Apply(Term.ApplyType(Term.Select(Term.Name("expr"), Term.Name("op1")), List(Type.Name("Int"))), List(Lit.Int(1), Lit.Int(2)))

但是scalac如果您使用-Xprint:typer运行代码

object Test5 {
  object expr {
    def op1(param1: Any, param2: Any): Unit = {}
    def op2[T](param1: Any, param2: Any): Unit = {}
  }

  expr.op1("", "", "")
  expr op1 ("", "", "")

  expr.op2[Int]("", "", "")
  expr op2[Int] ("", "", "")
}

你会看到在语法树中解析成对的后缀和中缀符号是相同的:

Test5.this.expr.op1("", "", "");
Test5.this.expr.op1("", "", "");
Test5.this.expr.op2[Int]("", "", "");
Test5.this.expr.op2[Int]("", "", "")