Scala Slick 3 Playframework -
kind of stuck trying port old php application scala, want: have nodes (model) this:
id | parent_id   now given node
case class node(id: option[long], parentid: option[long])  private def filterquery(id: long): query[nodes, node, seq] = nodes.filter(_.id === id)  override def find(id: long): future[option[node]] = {     try db.run(filterquery(id).result.headoption)     db.close }   i want parents recursively, like:
private def getallparents(node: node): list[node] = node.parentid match {   case l:long => list(node) + getallparents(find(l))   case none => list(node) }   of course doesn't work.
- the syntax not right. need add node list , call it's parent
 - the recursive call wouldn't work because expects node gets future[option[node]], not sure how resolve either :(
 
i remember doing haskell few years , functional style (huge) bit rusty.
edit: see need have list parameter well... argh, i'm stuck -.-
first, don't need include list parameter, need use nested function that.
the main issue here find returns future[option[node]], means need work entirely "inside" futures.  future monad, means 2 things:
- you can never directly access value inside 
future - you interact contained value passing functions through 
map,flatmap, give newfuturein return. 
i suggest read articles how future-based programming works, here's decent 1 found, simplified example, suppose have :
val x: future[int] = future { 5 }   if want add 1 contained value, cannot access directly, rather can call map:
val y: future[int] = x.map{i => + 1}   likewise, if have function :
def addone(i: int): future[int] = //...   i can use future :
val y: future[int] = x.flatmap{i => addone(i)}   getting situation, means getallparents must return future[list[node]] , recursion using flatmap, create new future every time call find , chain them traverse through them.
private def getallparents(node: node): future[list[node]] = {   def loop(node: node, build: list[node]): future[list[node]] = {     node.parentid match {       case none => future.successful(node :: build)       case some(parentid) => find(parentid).flatmap{parentoption => parentoption match {         case some(parentnode) => loop(parentnode, node :: build)         case none => throw new exception(s"couldn't find parent $node")       }}     }   }   loop(node, nil) }   so can see loop sort of recursive function, recursion done inside future.  if node has no parent, stick end result directly in new future , call day.  if node have parent, call find, gives future[option[node]].  
now recursion, call flatmap on returned future, , have give function of type option[node] => future[list[node]].  have function has access both node , parent, , can add node list , call loop again on parent.
Comments
Post a Comment