Scala通用宏

时间:2013-12-23 21:11:01

标签: scala generics macros

是否可以使用scala宏执行以下操作:

trait Cacheable {
  def cache[T](genValue: => Future[T]): Future[T] = macro Cacheable.cacheImpl[T]
}

object Cacheable {
  def cacheImpl[A: c.WeakTypeTag](c: Context)
                                 (genValue: c.Expr[Future[A]]): c.Expr[Future[A]] = {
    import c.universe._

    reify {
      genValue.splice
    }
  }
}

它不能在Cacheable trait中的宏函数调用中编译,并带有以下消息:

此行有多个标记 - 宏实现形状错误:必需: (c:scala.reflect.macros.Context)(genValue:c.Expr [=> scala.concurrent.Future [T]]):c .Expr [scala.concurrent.Future [T]]发现:(c: scala.reflect.macros.Context)(genValue:c.Expr [scala.concurrent.Future [A]]):c .Expr [scala.concurrent.Future [A]]参数genValue的类型不匹配:c.Expr [= > scala.concurrent.Future [T]]不符合c.Expr [scala.concurrent.Future [?A]] - 宏实现形状错误:必需:(c:scala.reflect.macros.Context)(genValue: c.Expr [=> scala.concurrent.Future [T]]):c .Expr [scala.concurrent.Future [T]] found:(c:scala.reflect.macros.Context)(genValue:c.Expr [scala.concurrent.Future [A]]):c .Expr [scala.concurrent.Future [A]]参数genValue的类型不匹配:c.Expr [=> scala.concurrent.Future [T]]不符合c.Expr [scala.concurrent.Future [?A]]

1 个答案:

答案 0 :(得分:-1)

首先让你的签名正确:

import concurrent.Future
import language.experimental.macros
import reflect.macros.Context

trait Cacheable {
  def cache[A](genValue: => Future[A]): Future[A] = macro Cacheable.cacheImpl[A]
}

object Cacheable {
  def cacheImpl[A: c.WeakTypeTag](c: Context)
                                 (genValue: c.Expr[Future[A]]): c.Expr[Future[A]] = ???
}

错误很明显:

<console>:12: error: macro implementation has wrong shape:
 required: (c: scala.reflect.macros.Context)(genValue: c.Expr[=> scala.concurrent.Future[A]]): c.Expr[scala.concurrent.Future[A]]
 found   : (c: scala.reflect.macros.Context)(genValue: c.Expr[scala.concurrent.Future[A]]): c.Expr[scala.concurrent.Future[A]]
type mismatch for parameter genValue: c.Expr[=> scala.concurrent.Future[A]] does not conform to c.Expr[scala.concurrent.Future[?A]]
         def cache[A](genValue: => Future[A]): Future[A] = macro Cacheable.cacheImpl[A]
                                                                           ^

您要求cache方法中的call-by-name参数,但在宏实现方法中使用eager类型。

没有相应的类型c.Expr[=> Future[A]],我非常怀疑可以表达这种类型。因为宏将表达式转换为Future[A],如果要“按需”使用该表达式,则必须在宏中生成的AST中提供一种机制。由于您的返回类型为Future[A],而不是() => Future[A],因此我不知道您将如何在此处实现此目标,或者您究竟想要实现的目标。