Accessing type parameters in Macros

147 views
Skip to first unread message

Julian Schrittwieser

unread,
Nov 18, 2012, 11:59:45 AM11/18/12
to scala...@googlegroups.com
I'm trying to create a System of Measurements with Scala Macros. As such, each number is represented by the actual value and it's unit:

case class Number[T](n: Int)

eg val a = Number[Meter](10)

If I add and multiply those numbers, I want to correctly handle the units (= the type parameter T). Normally, those wouldn't be accessible because of erasure, but I found TypeTags (http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.reflect.api.TypeTags), which are supposed to solve this problem. 

At first, this seems to work - directly creating a number and the printing it gives me the correct type parameter: http://pastebin.com/Yxxw7zN7

However, once I perform some arithmetic one those values with a macro, I don't get any concrete value for T, just T itself. (for a complete example see https://github.com/Mononofu/Units-of-Measure/)

I get the following output:

type of 2 has type arguments List(Meter)
type of 7 has type arguments List(T)
type of 12 has type arguments List(Times[T,U])
type of 17 has type arguments List(T)

I suspect this is because of the way I create expressions with reify - the multiplication_impl macro (used for the third line of output) returns an expression of type Number[Times[T, U]] in the last line, and this is exactly the type it shows to me. Do I need to resolve the type parameters somehow before creating the new expressions? (see https://github.com/Mononofu/Units-of-Measure/blob/master/macros/macro_impl.scala)

all the best, Julian


Julian Schrittwieser

unread,
Nov 18, 2012, 2:43:28 PM11/18/12
to scala...@googlegroups.com
Thanks to Paul for pointing out what I was doing wrong - I hadn't added the "T: WeakTypeTag" annotation everywhere I declared T, so the type was erased when I multiplied or added two numbers.

However, I still have a problem - the types are printed fine at run time, but I haven't yet managed to get at them during compile time (ie when the macro runs)

Adding an implicit parameter for the TypeTag ("(implicit tag: WeakTypeTag[Number[T]])") just makes it fail because the macro has an unexpected form, and getting the tag with "weakTypeTag[T]" doesn't work either. 

Are there any other options?

Eugene Burmako

unread,
Nov 19, 2012, 9:11:45 AM11/19/12
to scala-user
In a macro use c.weakTypeTag, not just weakTypeTag

On Nov 18, 8:43 pm, Julian Schrittwieser <j.schrittwie...@gmail.com>
wrote:
> Thanks to Paul for pointing out what I was doing wrong - I hadn't added the
> "T: WeakTypeTag" annotation everywhere I declared T, so the type was erased
> when I multiplied or added two numbers.
>
> However, I still have a problem - the types are printed fine at run time,
> but I haven't yet managed to get at them during compile time (ie when the
> macro runs)
>
> Adding an implicit parameter for the TypeTag ("(implicit tag:
> WeakTypeTag[Number[T]])") just makes it fail because the macro has an
> unexpected form, and getting the tag with "weakTypeTag[T]" doesn't work
> either.
>
> Are there any other options?
>
>
>
>
>
>
>
> On Sunday, November 18, 2012 5:59:45 PM UTC+1, Julian Schrittwieser wrote:
>
> > I'm trying to create a System of Measurements with Scala Macros. As such,
> > each number is represented by the actual value and it's unit:
>
> > case class Number[T](n: Int)
>
> > eg val a = Number[Meter](10)
>
> > If I add and multiply those numbers, I want to correctly handle the units
> > (= the type parameter T). Normally, those wouldn't be accessible because of
> > erasure, but I found TypeTags (
> >http://www.scala-lang.org/archives/downloads/distrib/files/nightly/do...),
> > which are supposed to solve this problem.
>
> > At first, this seems to work - directly creating a number and the printing
> > it gives me the correct type parameter:http://pastebin.com/Yxxw7zN7
>
> > However, once I perform some arithmetic one those values with a macro, I
> > don't get any concrete value for T, just T itself. (for a complete example
> > seehttps://github.com/Mononofu/Units-of-Measure/)
>
> > I get the following output:
>
> > type of 2 has type arguments List(Meter)
> > type of 7 has type arguments List(T)
> > type of 12 has type arguments List(Times[T,U])
> > type of 17 has type arguments List(T)
>
> > I suspect this is because of the way I create expressions with reify -
> > the multiplication_impl macro (used for the third line of output) returns
> > an expression of type Number[Times[T, U]] in the last line, and this is
> > exactly the type it shows to me. Do I need to resolve the type parameters
> > somehow before creating the new expressions? (see
> >https://github.com/Mononofu/Units-of-Measure/blob/master/macros/macro...
> > )
>
> > all the best, Julian
Reply all
Reply to author
Forward
0 new messages