Given this code:
import shapeless._
import poly._
object EverywhereValAndDef {
sealed trait Tree[T]
case class Leaf[T](t: T) extends Tree[T]
case class Node[T](left: Tree[T], right: Tree[T]) extends Tree[T]
val tree: Tree[Int] =
Node(
Node(
Node(
Leaf(1),
Node(
Leaf(2),
Leaf(3))),
Leaf(4)),
Node(
Leaf(5),
Leaf(6)))
object inc extends ->((i: Int) => i + 1)
def afterIncDef = everywhere(inc)(tree) // works
val afterIncVal = everywhere(inc)(tree) // fails
val expected: Tree[Int] =
Node(
Node(
Node(
Leaf(2),
Node(
Leaf(3),
Leaf(4))),
Leaf(5)),
Node(
Leaf(6),
Leaf(7)))
def eqDef = expected == afterIncDef
def eqVal = expected == afterIncVal
}
in a repl session I get this results:
Welcome to Scala version 2.11.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> EverywhereValAndDef.eqDef
res0: Boolean = true
scala> EverywhereValAndDef.eqVal
res1: Boolean = false
scala> EverywhereValAndDef.tree
res2: EverywhereValAndDef.Tree[Int] = Node(Node(Node(Leaf(1),Node(Leaf(2),Leaf(3))),Leaf(4)),Node(Leaf(5),Leaf(6)))
scala> EverywhereValAndDef.afterIncDef
res3: EverywhereValAndDef.Tree[Int] = Node(Node(Node(Leaf(2),Node(Leaf(3),Leaf(4))),Leaf(5)),Node(Leaf(6),Leaf(7)))
scala> EverywhereValAndDef.afterIncVal
res4: EverywhereValAndDef.Tree[Int] = Node(Node(Node(Leaf(1),Node(Leaf(2),Leaf(3))),Leaf(4)),Node(Leaf(5),Leaf(6)))
Why everywhere is not working in the val case?
If you move the definitions of Tree, Leaf and Node out of EverywhereValAndDef to the top level (or to some other object) then the problem goes away.
I don't have a definitive answer, but it would appear to be a subtle initialization order issue colliding with this Scala macros issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With