views:

182

answers:

3

I want to implement a prototype-based system in Scala. At the root of the type hierarchy is the ROOT node, which has a prototype that refers to itself.

The following code demonstrates what I'm trying to do:

class Node(val prototype: Node) {
    private def this() = this(this)
}

object Node {
    val ROOT = new Node
}

Unfortunately, this does not compile an error: "this can only be used in a class, object, or template".

The argument "this" for the call to the primary constructor is not accepted. This sounds reasonable, since the object is not yet created. However, since prototype is immutable, I can't set it to null and define it afterwards.

Any suggestions on how to do this properly in Scala?

I'm using Scala-2.8.0RC7.

+1  A: 

I don't quite see how you can do this - how can you have a constructed instance of the root node, if you need it to already exist when creating it? So the thing at fault here is your modelling of the problem domain, not Scala (or any other language for that matter)

Surely the root node could have a null prototype, or (more idiomatic scala) an Option prototype?

class Node private[mypackage](val prototype : Option[Node]) {
  private def this() = this(None)
  private def this(ptype : Node) = this(Some(ptype)) //Public c-tor
}

object Node extends (Node => Node) {
  val Root = new Node
  def apply(ptype : Node) = new Node(ptype)
}
oxbow_lakes
Referring to something that does not exist: that is the question. With mutables, this is easy. I wanted to do it in the same way as Python does typing: type(5) = <type 'int'>. type(int) = <type 'type'>. type(type) = <type 'type'>.
Frederik
Well - then don't make it immutable!
oxbow_lakes
+6  A: 

For this looks like you have two kinds of things (Root- and Simple-Nodes) What about this?

trait Node { def prototype: Node }

class RootNode extends Node { def prototype = this }

class SimpleNode(val prototype: Node) extends Node

In the REPL you can do this then:

scala> val rootNode = new RootNode
rootNode: RootNode = RootNode@191dd1d

scala> val n1 = new SimpleNode(rootNode)
n1: SimpleNode = SimpleNode@30e4a7

scala> val n2 = new SimpleNode(n1)
n2: SimpleNode = SimpleNode@3a0589

scala> n2.prototype.prototype
res0: Node = RootNode@191dd1d

I don't know, if that is what you are looking for.

michael.kebe
This seems like the best way to proceed. Thanks!
Frederik
After some careful consideration, I think defining "prototype" as a method seems like the best way.
Frederik
+2  A: 

You could also do the following. Maybe it is not the most idiomatic Scala code but it is short and I think it answers your question.

class Node(prot: Option[Node] = None) { def prototype = prot getOrElse this }
Ruediger Keller
Since my answer go edited to now use Option, I'd say it now is idiomatic Scala code. I didn't use Option originally so that there is no need to box nodes before passing them to the constructor.
Ruediger Keller
This is a very good idea, using prototype as a function instead of a property. I'm picking it as the preferred answer.
Frederik