简体   繁体   English

Scala 宏可以在这种情况下生成方法和隐含吗?

[英]Can Scala macros generate the methods and implictits in this situation?

I want to use scala macros to do some kind of code generation.我想使用 scala 宏来进行某种代码生成。 In specific, I define some Event types and these events will be pushed to the same method (here workImpl ) and return a value of a specific type.具体来说,我定义了一些Event类型,这些事件将被推送到同一个方法(这里workImpl )并返回一个特定类型的值。 The return type is not determined if I just call workImpl , because it handles different inputs and returns different results.如果我只是调用workImpl ,返回类型是不确定的,因为它处理不同的输入并返回不同的结果。 But the map between input types and output types is determined .但是输入类型和 output 类型之间的 map 是确定的 The goal is to make the return type available.目标是使返回类型可用。

Scala macro is fantastic and maybe helps. Scala 宏非常棒,可能会有所帮助。 I want to achieve auto code generation by add event return type annotation for each event type.我想通过为每个事件类型添加事件返回类型注释来实现自动代码生成。 The code that is supposed to be generated is code1 or code2 .应该生成的代码是code1code2

object A {
    private def workImpl(x: Any): Any = ???

    @anno(X_RET)
    case class X()

    @anno(Y_RET)
    case class Y()

    @anno(Z_RET)
    case class Z()

    // code1: auto generate work1 and the implicits
    def work1[T](x:T)(implicit ev: T=>M) = workImpl(x).asInstanceOf[M]
    implicit val X_TO_X_RET: X=>X_RET = null
    implicit val Y_TO_Y_RET: Y=>Y_RET = null
    implicit val Z_TO_Z_RET: Z=>Z_RET = null

    // code2: auto generate these methods
    def work2(x:X) = workImpl(x).asInstanceOf[X_RET]
    def work2(x:Y) = workImpl(x).asInstanceOf[Y_RET]
    def work2(x:Z) = workImpl(x).asInstanceOf[Z_RET]    
}

So, is this possible and how to achieve this?那么,这是否可能以及如何实现呢? If it is not possible, any solution else?如果不可能,还有其他解决方案吗?

I finally find a solution that works.我终于找到了一个可行的解决方案。

object A {
  private def workImpl(x: Any): Any = x match {
    case e: X => XRet(0)
    case e: Y => YRet(0)
    case e: Z => ZRet(0)
  }

  trait Event
  trait EventReturn[T] extends Event

  case class X() extends EventReturn[XRet]
  case class Y() extends EventReturn[YRet]
  case class Z() extends EventReturn[ZRet]

  case class XRet(x:Int)
  case class YRet(y:Int)
  case class ZRet(z:Int)

  def work3[T](x: EventReturn[T]): T = workImpl(x).asInstanceOf[T]

  def main(args: Array[String]): Unit = {
    work3(X()).x
    work3(Y()).y
    work3(Z()).z
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM