1

The Scala API docs for 2.10.3 say that I can, "Use refiy to produce the abstract syntax tree representing a given Scala expression." Accordingly, I can do:

scala> val uni = scala.reflect.runtime.universe 
uni: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse@4e42766

scala> uni reify { 1 to 3 } 
res2: uni.Expr[scala.collection.immutable.Range.Inclusive] = Expr[scala.collection.immutable.Range.Inclusive](Predef.intWrapper(1).to(3))

In the example above, I get what I am looking for: Predef.intWrapper(1).to(3)) (a handy expanded representation of the operations to be performed).

When I attempt to reify 1 + 3, however, I do not the representation of the operations to perform that I desire.

scala> uni reify { 1 + 3 }
res5: uni.Expr[Int(4)] = Expr[Int(4)](4)

Is this expected behavior? Is + a primitive operation and, hence, not reified?

The Scala docs show an example of reification that implies that an even more useful representation is available:

reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("$plus")), List( Literal(Constant(4)) ) )

How can I examine the proper expanded representation for 1 + 3 (if one exists) and how can I retrieve a detailed representation of any expression (immediately above)?

Edit: I see now that the representation show in the Scala docs is generated by showRaw. However, I still cannot reproduce the raw representation show in the example above for 2 + 4.

Andrew McKinlay
  • 431
  • 3
  • 15

1 Answers1

5

See this answer by Eugene Burmako:

macros are wired into typechecking (in the sense that macro arguments are typechecked prior to macro expansion), and typechecking folds constants

reify is implemented using macro.

You should just prevent constant folding like this:

{
  val i = 1
  showRaw{ reify{i + 2}.tree }
}
// Apply(Select(Ident(newTermName("i")), newTermName("$plus")), List(Literal(Constant(2))))
Community
  • 1
  • 1
senia
  • 37,745
  • 4
  • 88
  • 129
  • In order to use the your workaround, I would have to alter the code I am reifying. This is not always easy. Is there no other way? – Andrew McKinlay Jan 24 '14 at 19:27
  • Also, are the Scala docs for 2.10.3 wrong when it shows `reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("$plus")), List( Literal(Constant(4)) ) )`? – Andrew McKinlay Jan 24 '14 at 19:28
  • @AndrewMcKinlay: Note that in compile time `2 + 4` will be folded to `6` so there will be only a constant `6` in runtime. I don't know other way to prevent constant folding. If you are developing some kind of DSL you could use string interpolation like `math"1 + 2"`. – senia Jan 24 '14 at 19:32
  • @AndrewMcKinlay: I guess it's from an old version of macros behavior. – senia Jan 24 '14 at 19:34
  • So, did the previous macro system not type check macro arguments? – Andrew McKinlay Jan 25 '14 at 02:22
  • 1
    @AndrewMcKinlay: No, macros without arguments type check are `White Box macros` (see [Evolution of Scala Macros](http://www.infoq.com/presentations/scala-macros)), and they will be introduced only in `2.12`. I don't know the history of this error in documentation. – senia Jan 25 '14 at 04:11
  • 1
    Fixed the docs: https://github.com/scala/scala/pull/3414. That's a plain oversight in the documentation - macros have never behaved this way. Thanks for catching it and sorry for the confusion. – Eugene Burmako Jan 26 '14 at 08:39