functional programming - Scala case class prohibits call-by-name parameters? -
i want implement infinite list:
abstract class mylist[+t] case object mynil extends mylist[nothing] case class mynode[t](h:t,t: => mylist[t]) extends mylist[t] //error: `val' parameters may not call-by-name the problem call-by-name not allowed.
i've heard because val or var constructor parameter not allowed call-by-name. example:
class a(val x: =>int) //error: `val' parameters may not call-by-name but contradiction normal constructor parameter still val, despite private. example:
class a(x: =>int) // pass so question :
is problemval or var ? if that. since point call-by-name defer computation, why not val or var computation(or initialization) deferred? how around cass class implement infinite list?
there no contradiction: class a(x: => int) equivalent class a(private[this] val x: => int) , not class a(private val x: => int). private[this] marks value instance-private, while private-modifier without farther specification allows accessing value instance of class.
unfortunately, defining case class a(private[this] val x: => int) not allowed either. assume because case-classes need access constructor values of other instances, because implement equals method.
nevertheless, implement features case class provide manually:
abstract class mylist[+t] class mynode[t](val h: t, t: => mylist[t]) extends mylist[t]{ def gett = t // need able access t /* edit: actually, lead infinite recursion override def equals(other: any): boolean = other match{ case mynode(i, y) if (gett == y) && (h == i) => true case _ => false }*/ override def hashcode = h.hashcode override def tostring = "mynode[" + h + "]" } object mynode { def apply[t](h: t, t: => mylist[t]) = new mynode(h, t) def unapply[t](n: mynode[t]) = some(n.h -> n.gett) } to check code, try:
def main(args: array[string]): unit = { lazy val first: mynode[string] = mynode("hello", second) lazy val second: mynode[string] = mynode("world", first) println(first) println(second) first match { case mynode("hello", s) => println("the sec node " + s) case _ => println("false") } } unfortunately, not know sure why call-by-name val , var members prohibited. however, there @ to the lowest degree 1 danger it: think how case-classes implement tostring; tostring-method of every constructor value called. (and in illustration would) lead values calling infinitely. can check adding t.tostring mynode's tostring-method.
edit: after reading chris martin's comment: implementation of equals pose problem more severe implementation of tostring (which used debugging) , hashcode (which lead higher collision rates if can't take parameter account). have think how implement equals meaningfull.
scala functional-programming lazy-evaluation callbyname
No comments:
Post a Comment