Scala 3:创建 Expr[ Int => Int ]

问题描述

我在一个项目中使用 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]

解决方法

以下是用于构建新 givenToExpr “构建块”: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) } }