Why does Scala reify not work as according to the docs?

265 views Asked by At

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.

1

There are 1 answers

7
senia On BEST ANSWER

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))))