【问题标题】:Scala generic macroScala 通用宏
【发布时间】:2013-12-23 21:11:00
【问题描述】:

是否可以使用 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 特征中的宏函数调用中编译,并显示以下消息:

此行有多个标记 - 宏实现的形状错误:必需: (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]]

【问题讨论】:

    标签: scala generics macros


    【解决方案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 方法中要求一个按名称调用的参数,但在宏实现方法中使用了急切类型。

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

    【讨论】:

    • 感谢您的回复。我不是在寻找对代码 sn-p 的有效性或有用性的评论,也不是在寻找对错误消息的解释,而是在寻找这样的 sn-p 是否以另一种形式有效的答案。抱歉,如果我没有完全正确地表达它。
    猜你喜欢
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    相关资源
    最近更新 更多