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.

  1. the syntax not right. need add node list , call it's parent
  2. 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:

  1. you can never directly access value inside future
  2. you interact contained value passing functions through map , flatmap, give new future in 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

Popular posts from this blog

apache - PHP Soap issue while content length is larger -

asynchronous - Python asyncio task got bad yield -

javascript - Complete OpenIDConnect auth when requesting via Ajax -