此文档页面特定于 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]