Scala Inheritance; Builder Trouble; Non-Generic IterableLike -
i'm trying implement simple design goal, complexity of scala's type scheme gives me headache. after comparing of traversable, iterator, iterable, stream, view etc decision define custom trait (let's phone call stream
brevity)
stream[streamentry]
, want avoid meaningless types stream[int]
) has similar usage iterable
all members take
, drop
, etc should homecoming stream
, not basic iterable
. this have tried far:
approach 1to sketch utilize case, simple illustration (which violates 3rd design goal) be:
case class streamentry(data: double) // dummy trait stream extends iterable[streamentry] { val metainfo: string } // illustration utilize case val s = new stream { val metainfo = "something" val iterator = streamentry(1) :: streamentry(2) :: streamentry(3) :: nil toiterator } val t = s.take(1) // unfortunately, no longer stream
approach 2 this 3rd requirement calls usage of template trait instead of base trait (i hope standard terminology refer either somecollection or somecollectionlike). means have utilize iterablelike[streamentry, stream]
redefines homecoming types of representing collection iterable
extends iterablelike[a, iterable[a]]
homecoming iterable
s. thought pretty much same iterable
does. be:
// way `iterable` defined, non-generic trait stream extends traversable[streamentry] geniterable[streamentry] generictraversabletemplate[streamentry, stream] iterablelike[streamentry, stream] { ... }
unfortunately, not compile because stream
appears template argument generictraversabletemplate
, compiler requires template argument (exactly one) stream
itself, makes sense.
starting here, got lost in type system. removing with generictraversabletemplate
leads incompatible type of newbuilder
, illegal inheritance due conflicts in type parameters in generictraversabletemplate
geninterable
, traversable
.
maybe closest solution following:
trait stream extends traversablelike[streamentry, stream] iterablelike[streamentry, stream] { val metainfo: string def seq = def newbuilder: scala.collection.mutable.builder[streamentry, stream] = ??? }
this compiles unfortunately have no thought how implement builder. possible reuse generic builder non-generic trait? though can go without builder because never want build new stream
other collections. i'm experiencing unusual runtime behavior approach, cannot understand. instance:
val s = new stream { val metainfo = "something" val iterator = streamentry(1) :: streamentry(2) :: streamentry(3) :: nil toiterator } // executing next independently (not in sequence) results in: s.take(1) // throws: scala.notimplementederror: implementation missing // seems require builder :( s.toarray // works s.toiterator // works s.toiterable // throws: java.lang.classcastexception: cannot cast scala.collection.iterable
now sense lost in depth of scala type system. still on right track lastly approach , builder missing piece in puzzle?
and how builder implementation non-generic non-cached type? straightforward thought implement +=
utilize mutable buffer, much against utilize iterators in first place... , how should implement to
fellow member if don't know how build class of type? guess relevant code must somewhere in library, can't dig out.
wow! you've got lot going on there...
here things should know or consider in solving design problem...
terminology:
we don't refer "template"s, phone call them "generic" or "parameterized" types. reason these types are not templates! is, they're not filled in actual type parameters create new classes each time they're used (as case in c++, rightly uses term "template"). instead, 1 class created (*) , serves every instantiation of generic type particular type parameters.design & language factors:
you say:
… non-generic (my stream semantically makes sense stream[streamentry] , want avoid meaningless types stream[int])
the requirement does not argue non-generic class. rather essence of "type bound" is. e.g.:
class generic[t <: upperbound](ctorargs...) { }
in case, class generic
may instantiated types subtypes of upperbound
. (note whenever "subtype" mean reflexive subtype relationship. in other words, every type subtype of under definition.
the upshot:
i wonder "stream" class or or has not satisfied existing type in scala standard library? you've discovered extending standard library collection classes not exclusively trivial, though doable. think doing not simple exercise in scala programming , shouldn't attempted 1 of first forays scala.
(*) oversimplification suffices purpose of explanation.
scala inheritance iterator builder
No comments:
Post a Comment