i'm trying define class have field set, , able manipulate set directly container class:
case class myclass(prop: string) extends traversablelike[int,myclass] { private def myset: set[int]() = set() override def foreach[u](f: int => u) = data.foreach[u](f) override def newbuilder: builder[int, myclass] = new arraybuffer[int] mapresult (a => myclass(prop, a.toset)) implicit def canbuildfrom: canbuildfrom[myclass, int, myclass] = new canbuildfrom[myclass, int, myclass] { def apply(): builder[int, myclass] = newbuilder def apply(from: myclass): builder[int, myclass] = newbuilder } }
i'd able do
var obj = myclass("hello") obj += 1 obj = obj map (_+1)
the first instruction (obj+= 1) works, second doesn't. problem can't put implicit canbuildfrom object myclass because builder needs informations dependant of instance (in case, prop field).
is there solution make implicit accessible , keep instance dependance ? i'd avoid making class mutable.
there couple of problems code:
set[int]()
not valid typemyset
, should drop()
- member
myset
shouldval
, notdef
- you calling apply() methods don't exist
- if want hook in collections hierarchy @ traversable level, don't methods
+
, derived+=
. if you're representing set, shouldset
.
here's revised attempt:
import mutable.builder import generic.canbuildfrom class myclass private (val prop: string, private val myset: set[int] = set()) extends immutable.set[int] setlike[int, myclass] { def -(elem: int) = myclass(prop, myset - elem) def +(elem: int) = myclass(prop, myset + elem) def contains(elem: int) = myset.contains(elem) def iterator = myset.iterator override def empty: myclass = myclass(prop) override def stringprefix = "myclass(" + prop + ")" } object myclass { def defaultprop = "defaultprop" def apply(prop: string, myset: set[int] = set()) = new myclass(prop, myset) def newbuilder(prop: string = defaultprop): builder[int, myclass] = set.newbuilder[int] mapresult (set => myclass(prop, set)) implicit def canbuildfrom: canbuildfrom[myclass, int, myclass] = new canbuildfrom[myclass, int, myclass] { def apply(): builder[int, myclass] = newbuilder() def apply(from: myclass): builder[int, myclass] = newbuilder(from.prop) } }
then can write:
var obj = myclass("hello") obj += 1 println(obj) // prints myclass(hello)(1) obj = obj map (_ + 1) println(obj) // prints myclass(hello)(2)
let's dissect that:
myclass
explicitly immutable set custom representation declared in type arguments setlike
. prop
public val member; actual set, myset
, private val.
then need implement 4 operations on set
relies, forwarding them myset
. (this looks factored out. seq
s, there class seqforwarder
similar job; couldn't find setforwarder
, though). finally, provide empty
method, on built-in inherited builder relies. finally, overriding stringprefix
enables nicer string representation "myclass" , value of prop
.
note canbuildfrom
object myclass
calls newbuilder
, passing prop
of original collection when can. means of time, can keep value while mapping, etc. on myclass
instances. need define default value prop
, however, since canbuildfrom
s must define apply
method not tell originating collection is. (question: why happen?)
finally, our implementation of newbuilder
not rely on arraybuffer
s more, directly builds set
instance wrapped new myclass
instance.
some more resources:
Comments
Post a Comment