scala - How to pass an implicit parameter from an instance? -


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 type myset, should drop ()
  • member myset should val, not def
  • you calling apply() methods don't exist
  • if want hook in collections hierarchy @ traversable level, don't methods + , derived +=. if you're representing set, should set.

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. seqs, 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 canbuildfroms must define apply method not tell originating collection is. (question: why happen?)

finally, our implementation of newbuilder not rely on arraybuffers more, directly builds set instance wrapped new myclass instance.

some more resources:


Comments