简体   繁体   中英

Passing type Parameter to reify while implementing a scala macro

Going from the following macro implementation, which is working as expected, i would like to remove the hard coded Account and replace it with a variable beeing passed as type parameter T:c.WeakTypeTag to the macro by the caller. how should the macro be modified so that i can pass any type T?

`

import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
import com.xy.iws.model.Model._
import com.xy.iws.repo.dao.DAO._
import com.xy.iws.service.run
import com.xy.iws.service.Api
import com.xy.iws.service.Request._

 object makeService {
    def make[T]:Api[Account] = macro makeImpl[T]
   def makeImpl[T:c.WeakTypeTag](c: Context): c.Expr[Api[Account]] = c.universe.reify {
//val source = c.weakTypeOf[T]
import com.xy.iws.service.Request._
implicit val api = new Api[Account] {
  def create():Int = {run.runG[Int](Create[Account])}
  def all(): List[Account] = run.runG[List[Account]](new FindAll[Account])
  def insert(model: List[Account]) =  run.runG[Int](new Insert[Account](model))
  def findSome(id: String): List[Account] = run.runG[List[Account]](new FindSome[Account](id))
  def find(id: String): List[Account] = run.runG[List[Account]](new Find[Account](id))
  def update(item: Account): List[Account] = {
    val i = run.runG[List[Account]](new Find[Account](item.id))
    if (i.size > 0) {
      val updateAccount = run.runG[Int](new Update[Account](item.id, item.name))
    }else {
      insert(List(item))
    }
    run.runG[List[Account]](new FindAll[Account])
  }
  def delete(id: String): List[Account] = {
    run.runG[Int](new Delete[Account](id))
    run.runG[List[Account]](new FindAll[Account])
   }
  }
api
 }
}

`

maybe you can use quasiquotes

abstract class Api[T] {
  def a: Int

  def b: Int

  def t: List[T]
}

object Reify {
  def apply[T](initValue: T): Api[T] = macro impl[T]

  def impl[T: c.WeakTypeTag](c: Context)(initValue: c.Expr[T]): c.Tree = {
    import c.universe._
    val t = c.weakTypeOf[T].typeSymbol.name.toTypeName
    q"""
      val api = new Api[$t] {
       def a = 1
       def b = 2
       override def t= List(${initValue})
     }
     api
    """
  }
}

---use like this

object ReifyUsing extends App {
  import macross.Reify
  import macross.Api
  println(Reify.apply[String]("String").t)
}

Thank you that was the hint i was looking for as answer to my question:

How to pass pass parameter in particular type parameter to the implementation of a macro?

Short answer: Use quasiquote

See the implementation below that did the job `

 import scala.language.experimental.macros
 import scala.reflect.macros.whitebox.Context
 import com.xy.iws.model.Model._
 import com.xy.iws.repo.dao.DAO._

  object makeService {

   import com.xy.iws.service.Api
   import com.xy.iws.service.Request

  def make[T]:Api[T] = macro makeImpl[T]
  def makeImpl[T:c.WeakTypeTag](c: Context): c.Tree = {

   import c.universe._
   val t = c.weakTypeOf[T].typeSymbol.name.toTypeName
   q"""
       implicit val api = new Api[$t] {
         override def create():Int = {run.runG[Int](Create[$t])}
         override def all(): List[$t] = run.runG[List[$t]](new FindAll[$t])
         override def insert(model: List[$t]) =  run.runG[Int](new Insert[$t](model))
         override def findSome(id: String): List[$t] = run.runG[List[$t]](new     FindSome[$t](id))
         override def find(id: String): List[$t] = run.runG[List[$t]](new Find[$t](id))
         override def update(item: $t): List[$t] = {
       val i = run.runG[List[$t]](new Find[$t](item.id))
       if (i.size > 0) {
         run.runG[Int](new Update[$t](item.id, item.name))
       }else {
         insert(List(item))
       }
        run.runG[List[$t]](new FindAll[$t])
     }
     override def delete(id: String): List[$t] = {
       run.runG[Int](new Delete[$t](id))
       run.runG[List[$t]](new FindAll[$t])
  }
}
api
"""
 }
}

` and i use the macro like this:

object Main { def main(args: Array[String]) {
import com.xy.iws.service.Api println(makeService.make[Account].all +" account objects") println(makeService.make[Article].all +" article objects") println(makeService.make[Supplier].all +" supplier objects") } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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