此文档页面特定于 Scala 3,可能涵盖 Scala 2 中不可用的新概念。 除非另有说明,否则此页面中的所有代码示例都假设您使用的是 Scala 3。
我应该使用哪个 Expr(...) 或 '{...}?
如果您可以在编译时使用 Expr(...) 编写代码,则会在编译时进行更多评估。 仅当您确实需要在运行时稍后评估代码时才使用 '{...},通常是因为它依赖于运行时值。
Expr(true) 和 '{true} 之间哪个更好?
所有包含基本类型值的引号都被优化为 Expr.apply。 在您的项目中选择一个,并坚持使用单一符号以避免混淆。
如何从 Expr 中获取值?
如果表达式表示一个值,可以使用 .value、.valueOrAbort 或 Expr.unapply
如何获取 Expr 的精确类型?
我们可以使用以下模式匹配获取 Expr 的精确类型 (Type)
val x: Expr[X] = ...
x match
case '{ $x: t } =>
// `x: Expr[X & t]` where `t` is the precise type of `x`
如何调用元组类型的所有类型?
如果我有一个类型 (T1, T2, ...),如何生成 (summon[T1], summon[T2], ...) 的项,或者获取带有调用值的单个表达式?
根据您的用例,调用它们的方式会有所不同。特别是,您需要的代码取决于您想要的输出类型 (Expr[Tuple]、List[Expr[Any]] 或其他类型) 以及您需要如何报告错误。以下两个示例应该为您提供这两种代码变体的基本框架。
def summonAllInList[T](using Type[T])(using Quotes): List[Expr[Any]] = {
Type.of[T] match
case '[ head *: tail ] =>
Expr.summon[head] match
case Some(headExpr) => headExpr :: summonAllInList[tail]
case _ => quotes.reflect.report.throwError(s"Could not summon ${Type.show[head]}")
case '[ EmptyTuple ] => Nil
case _ => quotes.reflect.report.throwError(s"Could not `summonAllInList` of tuple with unknown size: ${Type.show[T]}")
}
def summonAll[T](using Type[T])(using Quotes): Option[Expr[Tuple]]] = {
Type.of[T] match
case '[ head *: tail ] =>
for headExpr <- Expr.summon[head]
tailExpr <- summonAll[tail]
yield '{ headExpr *: tailExpr }
case '[ EmptyTuple ] => Some('{ EmptyTuple })
case _ => None
}
如何为静态未知类型调用表达式?
您可以从 TypeRepr 或 Type 调用表达式,如下所示。
如果您有 TypeRepr,请使用
val tpe: TypeRepr = ...
Implicits.search(tpe) match
case result: ImplicitSearchSuccess => result.tree
case _ =>
相反,如果您有 Type[_],请使用
val tpe: Type[_] = ...
tpe match
// (1) Use `a` as the name of the unknown type and (2) bring a given `Type[a]` into scope
case '[a] => Expr.summon[a]