I need to reify an expression of a spliced function. Unfortunately, reify does not work as expected when you append a wildcard. Instead of selecting the function which is being spliced it acts as if the spliced function were a value.
An example to illustrate the issue.
Welcome to Scala version 2.10.0-RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37). Type in expressions to have them evaluated. Type :help for more information. scala> import scala.reflect.runtime.{universe=>ru} import scala.reflect.runtime.{universe=>ru} scala> def f(x: Int) = 0 f: (x: Int)Int scala> val g = ru.reify(f _) g: reflect.runtime.universe.Expr[Int => Int] = Expr[Int => Int]({ ((x) => f(x))
})
scala> ru.reify(g.splice _) res0: reflect.runtime.universe.Expr[() => Int => Int] = Expr[() => Int => Int]((() => { ((x) => f(x))
}))
I would have expected an Expr[Int => Int]. Is this a bug? Is there a workaround?
> I need to reify an expression of a spliced function. Unfortunately, reify
> does not work as expected when you append a wildcard. Instead of selecting
> the function which is being spliced it acts as if the spliced function were
> a value.
> An example to illustrate the issue.
> Welcome to Scala version 2.10.0-RC2 (Java HotSpot(TM) 64-Bit Server VM,
> Java 1.6.0_37).
> Type in expressions to have them evaluated.
> Type :help for more information.
> scala> import scala.reflect.runtime.{universe=>ru}
> import scala.reflect.runtime.{universe=>ru}
> scala> def f(x: Int) = 0
> f: (x: Int)Int
> scala> val g = ru.reify(f _)
> g: reflect.runtime.universe.Expr[Int => Int] =
> Expr[Int => Int]({
> ((x) => f(x))})
> reify typechecks its arguments before doing any processing, so it > behaves exactly like normal Scala does:
> scala> val g1 = f _ > g1: Int => Int = <function1>
> scala> val g2 = g1 _ > g2: () => Int => Int = <function0>
> Why it behaves like that is another question.
> On Nov 15, 1:36 am, Léonard Schneider <leonard.schnei...@gmail.com> > wrote: > > Hi,
> > I need to reify an expression of a spliced function. Unfortunately, > reify > > does not work as expected when you append a wildcard. Instead of > selecting > > the function which is being spliced it acts as if the spliced function > were > > a value.
> > An example to illustrate the issue.
> > Welcome to Scala version 2.10.0-RC2 (Java HotSpot(TM) 64-Bit Server VM, > > Java 1.6.0_37). > > Type in expressions to have them evaluated. > > Type :help for more information. > > scala> import scala.reflect.runtime.{universe=>ru} > > import scala.reflect.runtime.{universe=>ru} > > scala> def f(x: Int) = 0 > > f: (x: Int)Int > > scala> val g = ru.reify(f _) > > g: reflect.runtime.universe.Expr[Int => Int] = > > Expr[Int => Int]({ > > ((x) => f(x))})
> Op donderdag 15 november 2012 10:38:29 UTC+1 schreef Eugene Burmako het > volgende:
>> reify typechecks its arguments before doing any processing, so it >> behaves exactly like normal Scala does:
>> scala> val g1 = f _ >> g1: Int => Int = <function1>
>> scala> val g2 = g1 _ >> g2: () => Int => Int = <function0>
>> Why it behaves like that is another question.
>> On Nov 15, 1:36 am, Léonard Schneider <leonard.schnei...@gmail.com> >> wrote: >> > Hi,
>> > I need to reify an expression of a spliced function. Unfortunately, >> reify >> > does not work as expected when you append a wildcard. Instead of >> selecting >> > the function which is being spliced it acts as if the spliced function >> were >> > a value.
>> > An example to illustrate the issue.
>> > Welcome to Scala version 2.10.0-RC2 (Java HotSpot(TM) 64-Bit Server VM, >> > Java 1.6.0_37). >> > Type in expressions to have them evaluated. >> > Type :help for more information. >> > scala> import scala.reflect.runtime.{universe=>ru} >> > import scala.reflect.runtime.{universe=>ru} >> > scala> def f(x: Int) = 0 >> > f: (x: Int)Int >> > scala> val g = ru.reify(f _) >> > g: reflect.runtime.universe.Expr[Int => Int] = >> > Expr[Int => Int]({ >> > ((x) => f(x))})
I've tried that but it failed for my use case. So let me describe the more general problem I'm trying to solve. Any idea or hint is welcome.
// Challenge: write macro getf such as "def g = getf[A.type]" == "def g = A.f _" for any A object // which contains a f method which can have any type signature // This is just an example of an A object containing an f method // object A { // def f(x: Int, s: String) // }
So here is a failed attempt to fix ideas. It shows why I've been trying to use the splice and wildcard combination in a reify. I think my initial question was a bad example to that regard.
> c.Expr(treeBuild.mkAttributedIdent(weakTypeOf[T].member(newTermName("f"))))
> }
> scala> def g = getf[A.type]
> <console>:12: error: missing arguments for method f in object A;
> follow this method with `_' if you want to treat it as a partially applied > function
> def g = getf[A.type]
On Thursday, November 15, 2012 12:46:18 PM UTC+1, Léonard Schneider wrote:
> Hi Dave,
> I've tried that but it failed for my use case. So let me describe the more > general problem I'm trying to solve. Any idea or hint is welcome.
> // Challenge: write macro getf such as "def g = getf[A.type]" == "def g = > A.f _" for any A object
> // which contains a f method which can have any type signature
> // This is just an example of an A object containing an f method
> // object A {
> // def f(x: Int, s: String)
> // }
OK. Answering myself. Here is what I came up with. It would still need to be made more robust by dealing with nullary methods for instance. In a few words, you have to redefine a function which takes the method values, as a lambda expression would, to be able to use it later on. I should be able to use the trick for automatically transform case classes into HList in my implementation ;)
object A {
def f(x: Int, s: String) = 0
}
def getf[T]: Any = macro getfImpl[T]
def getfImpl[T: c.WeakTypeTag](c: Context) = {
import c.universe._
val fSym = weakTypeOf[T].member(newTermName("f")).asMethod val argSyms = fSym.paramss.flatten
val funTree = Function(argSyms.map(ValDef(_)), treeBuild.mkMethodCall(fSym, argSyms.map(s =>
treeBuild.mkAttributedIdent(s)
)))
c.Expr(funTree)
}
On Thursday, November 15, 2012 6:53:36 PM UTC+1, Léonard Schneider wrote:
> So here is a failed attempt to fix ideas. It shows why I've been trying to > use the splice and wildcard combination in a reify. I think my initial > question was a bad example to that regard.
>> c.Expr(treeBuild.mkAttributedIdent(weakTypeOf[T].member(newTermName("f"))))
>> }
>> scala> def g = getf[A.type]
>> <console>:12: error: missing arguments for method f in object A;
>> follow this method with `_' if you want to treat it as a partially >> applied function
>> def g = getf[A.type]
> On Thursday, November 15, 2012 12:46:18 PM UTC+1, Léonard Schneider wrote:
>> Hi Dave,
>> I've tried that but it failed for my use case. So let me describe the >> more general problem I'm trying to solve. Any idea or hint is welcome.
>> // Challenge: write macro getf such as "def g = getf[A.type]" == "def g = >> A.f _" for any A object
>> // which contains a f method which can have any type signature
>> // This is just an example of an A object containing an f method
>> // object A {
>> // def f(x: Int, s: String)
>> // }
> Welcome to Scala version 2.10.0-RC2 (Oracle JRockit(R), Java 1.6.0_37).
> Type in expressions to have them evaluated.
> Type :help for more information.
> OK. Answering myself. Here is what I came up with. It would still need to > be made more robust by dealing with nullary methods for instance. In a few > words, you have to redefine a function which takes the method values, as a > lambda expression would, to be able to use it later on. I should be able to > use the trick for automatically transform case classes into HList in my > implementation ;)
> On Thursday, November 15, 2012 6:53:36 PM UTC+1, Léonard Schneider wrote:
>> So here is a failed attempt to fix ideas. It shows why I've been trying >> to use the splice and wildcard combination in a reify. I think my initial >> question was a bad example to that regard.
>>> c.Expr(treeBuild.mkAttributedIdent(weakTypeOf[T].member(newTermName("f"))))
>>> }
>>> scala> def g = getf[A.type]
>>> <console>:12: error: missing arguments for method f in object A;
>>> follow this method with `_' if you want to treat it as a partially >>> applied function
>>> def g = getf[A.type]
>> On Thursday, November 15, 2012 12:46:18 PM UTC+1, Léonard Schneider wrote:
>>> Hi Dave,
>>> I've tried that but it failed for my use case. So let me describe the >>> more general problem I'm trying to solve. Any idea or hint is welcome.
>>> // Challenge: write macro getf such as "def g = getf[A.type]" == "def g >>> = A.f _" for any A object
>>> // which contains a f method which can have any type signature
>>> // This is just an example of an A object containing an f method
>>> // object A {
>>> // def f(x: Int, s: String)
>>> // }