Is it possible to write a scala macro whose return depends on the argument?

For DSL, I would like to do something like:

object Creator { 
   def create[T](s :String) :Foo[T] = macro createImpl[T]
   def createImpl[T](c :Context)(s :c.Expr[String]) : c.Expr[Foo[T]] = {
        reify(new Foo[Any]())
   }
 }

My problem is to replace Anyreify with something that will return a properly parameterized version.

(I use a string argument above, but in the final version I plan to use a companion object of class T as a marker to determine the type of the argument of function 1 [T, Unit])

+1
source share
1 answer

You required: a) write new Foo[T]()instead of new Foo[Any]()(easy) b) transfer to the macro view of a type T, namely the type of value AbsTypeTag[T], declaring a parameter Tvia binding to the context: [T: c.AbsTypeTag].

, Scala 2.10.0-M7. Edit. 2.10.0-RC1 AbsTypeTag WeakTypeTag. .

Creator.scala:

import language.experimental.macros
import reflect.macros.Context
class Foo[T]
object Creator {
  def create[T](s: String): Foo[T] = macro createImpl[T]
  def createImpl[T: c.AbsTypeTag](c: Context)(s: c.Expr[String]): c.Expr[Foo[T]] = {
    import c.universe._
    reify(new Foo[T]())
  }
}

MacroClient.scala:

object Main extends App {
  println (Creator.create[Int](""))
}

, , :

scala> Creator.create[Int]("")
res2: Foo[Int] = Foo@4888884e

scala> Creator.create("")
<console>:12: error: macro has not been expanded
              Creator.create("")
                      ^

:

( , T [T, Unit])

, . Creator.create[T](otherArgs) - Creator.create(T, otherArgs), ( ). : class A object A , : A, A.type, A , A.


: Creator create Foo Foo, Foo. Any reify, , . , , Creator.create T, Any; .

. Creator create Foo Foo Creator.create, , Foo.type, Foo . Scala - , . , , .

trait Companion[Class]
//How to declare a companion
class Foo
object Foo extends Companion[Foo]
/*I'm cheating: an implementation of Companion does not need to be a true Companion. You can add documentation to explain how Companion is supposed to be used. */
object Bar extends Companion[Foo]
//But this is also useful - you can't create your own companion objects for pre-existing types, but you can still create the right instances of Companion:
object pInt extends Companion[Int]
object Creator {
  //T with Companion[S] is needed to workaround a type inference bug (SI-5298) and allow S to be correctly inferred.
  def create[S, T <: Companion[S]](obj: T with Companion[S]): S = ???
}

, -, , . ( S create) - , , .

, , :

import language.experimental.macros
import reflect.macros.Context
class Foo[T]
object Creator {
  //T with Companion[S] is needed to workaround a type inference bug (SI-5298) and allow S to be correctly inferred.
  def create[S, T <: Companion[S]](obj: T with Companion[S]): Foo[S] = macro createImpl[S, T]
  def createImpl[S: c.AbsTypeTag, T <: Companion[S]: c.AbsTypeTag](c: Context)(obj: c.Expr[T with Companion[S]]): c.Expr[Foo[S]] = {
    import c.universe._
    reify(new Foo[S]())
  }
}
+2

All Articles