Companion object in Scala isn't associating itself with case class
I'm having some trouble understanding why this code won't work. I got it from 99 Scala Problems in the Binary Trees section (http://aperiodic.net/phil/scala/s-99/). It looks valid to me: the Node object is a companion object to the Node class, and it's adding a constructor for leafs on the tree. But when I try compiling it, I get the following:
<console>:10: error: too many arguments for method apply: (value: T)Node[T] in object Node
def apply[T](value: T): Node[T] = Node(value, End, End)
If I remove both Ends, I don't get any compile errors, but if I make a Node with a single value I get stuck in an infinite loop. So it looks like apply is constructing more Node objects, and isn't associating itself with the Node class.
Any help is appreciated.
sealed abstract class Tree[+T]
case class Node[+T](value: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
override def toString = "."
}
object Node {
def apply[T](valu开发者_开发技巧e: T): Node[T] = Node(value, End, End)
}
Works for me (see below). Have you defined them in the same file?
Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :paste
// Entering paste mode (ctrl-D to finish)
sealed abstract class Tree[+T]
case class Node[+T](value: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
override def toString = "."
}
object Node {
def apply[T](value: T): Node[T] = Node(value, End, End)
}
// Exiting paste mode, now interpreting.
defined class Tree
defined class Node
defined module End
defined module Node
scala> Node("123")
res0: Node[java.lang.String] = T(123 . .)
scala>
Edit
From your comment: it looks like the :load
command in the repl interprets each line in the file one by one, you can find the code for that here. However this doesn't work using the REPL since (I believe) each line that is interpreted gets compiled in its own package. See this thread for more details. Perhaps this could be a future enhancement in the REPL. But in principle, there is nothing wrong with your code: using both :paste
mode or just compiling with scalac
works fine.
scala> case class A(i: Int, i2: Int)
defined class A
scala> object A {
| def apply(i: Int): A = A(i, i)
| }
:25: error: too many arguments for method apply: (i: Int)A in object A
def apply(i: Int): A = A(i, i)
scala> object A {
def apply(i: Int): A = new A(i, i)
}
defined module A
warning: previously defined class A is not a companion to object A.
Companions must be defined together; you may wish to use :paste mode for this.
N.B. I couldn't find any enhancement request on JIRA, so I created this issue
精彩评论