为什么无形的`无处不在`组合器在一个方法中工作但不在`val`中工作?

时间:2014-11-27 11:12:32

标签: scala shapeless

鉴于此代码:

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

}

在repl会话中我得到了这个结果:

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

为什么everywhereval案例中无效?

1 个答案:

答案 0 :(得分:3)

如果您将TreeLeafNode的定义从EverywhereValAndDef移到顶层(或其他某个对象),则问题就会消失。

我没有明确的答案,但这似乎是与此Scala宏issue发生冲突的微妙初始化顺序问题。