问题描述
我在一个项目中使用 Scala3 宏,但我一直在创建函数的 Expr
(和 ToExpr
)。
我有这样的东西:
case class Foo(f : Int => Int)
given ToExpr[Foo] with {
def apply(foo : Foo) = foo match {
case Foo(f) => '{Foo(???)} // <-- here
}
}
我不知道如何用 Expr[Int => Int]
替换上面的 ???
。
编辑:这是@GaelJ 的一些失败尝试
1) 第一次尝试
def apply(foo : Foo) = foo match {
case Foo(f) =>
val ff: Expr[Int => Int] = '{ (x: Int) => f.apply(x) }
'{Foo($ff)}
}
给出:
| val ff: Expr[Int => Int] = '{ (x: Int) => f.apply(x) }
| ^
| access to value f from wrong staging level:
| - the deFinition is at level 0,| - but the access is at level 1.
2) 第二次尝试
def apply(foo : Foo) = foo match {
case Foo(f) =>
val ff: Expr[Int => Int] = '{ (x: Int) => ($f).apply(x) }
'{Foo($ff)}
}
给出:
| val ff: Expr[Int => Int] = '{ (x: Int) => ($f).apply(x) }
| ^
| Found: (f : Int => Int)
| required: quoted.Expr[Any]
解决方法
以下是用于构建新 given
的 ToExpr
“构建块”:scala3 docs ToExpr。从我看来,不可能为函数构造 ToExpr
。
另一种尝试可能是:
def apply(foo : Foo)(using Quotes) = foo match {
case Foo(f) => {
val expr = to[Int,Int](a => Expr(f(a.valueOrError)))
'{Foo($expr)}
}
}
def to[T: Type,R: Type](f: Expr[T] => Expr[R])(using Quotes): Expr[T => R] =
'{ (x: T) => ${ f('x) } }