Scala 表达式之间的区别
Difference Between Scala Expressions
直到最近,我才了解到下面的两个 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,...)
在这种情况下,我不明白他们的目的是什么。它们什么时候有用?为什么允许它们用于中缀操作而不是 "apply-select" 操作 (expr.op(arg1, arg2,...)
)?
这些类型不是参数类型,而是泛型。例如:
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]("", "", "")
直到最近,我才了解到下面的两个 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,...)
在这种情况下,我不明白他们的目的是什么。它们什么时候有用?为什么允许它们用于中缀操作而不是 "apply-select" 操作 (expr.op(arg1, arg2,...)
)?
这些类型不是参数类型,而是泛型。例如:
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]("", "", "")