1

I have a function that perform a calc but i'm using a var to receive the value of a recursive function and i would like to avoid mutable variables.

def scoreNode(node:Option[Tree], score:Double = 0, depth:Int = 0):Double = {
  node.map(n => {
    var points = score
    n.children.filter(n => n.valid == Some(true)).foreach(h => {
      points = scoreNode(Some(h), 10, depth+1)
    })
    points
  }).getOrElse(score)
}

How can i rewrite this piece of code without a mutable variable? I've tried

5
  • You'll often find that any time you accept an argument of Option and immediately map on it, that your code gets easier to manage if you change the type signature to accept the non-optional type and map at the call site. That would remove some of the noise here and make it easier for you to see the behavior alone Commented Nov 5, 2016 at 12:57
  • What do you mean? I come from OO and FP seens obscure to me. Could you give an example? Commented Nov 5, 2016 at 12:59
  • 1
    Don't write scoreNode(node: Option[Tree], ...) = node.map(...) instead write scoreNode(node: Tree, ...) = ... and call it by maybeNode.map(scoreNode).getOrElse(defaultScore) Commented Nov 5, 2016 at 13:06
  • have you considered using pattern matching? Recursion and Pattern matching goes well with Scala way of doing stuff and avoiding mutation Commented Nov 5, 2016 at 13:36
  • @DevZer0 i don't know how to do it! lol Commented Nov 5, 2016 at 14:13

2 Answers 2

1

What you are essentially doing is summing something over all the nodes in a tree. Try to write a more idiomatic code, like this.

def scoreNode(node:Option[Tree], depth:Int = 0):Double =
    (for {
        n <- node
        h <- n.children
        if h.valid == Some(true)
        res = scoreNode(Some(h), depth + 1) + scala.math.pow(0.8, depth)
    } yield res).sum

I do not guarantee this works completely. It is your homework to make it right.

Sign up to request clarification or add additional context in comments.

Comments

0

You can use fold:

def scoreNode(node:Option[Tree], score:Double = 0, depth:Int = 0):Double = 
  node
    .map(_.children.filter(n => n.valid == Some(true)).fold(score)((acc, h) => scoreNode(Some(h), acc + scala.math.pow(0.8, depth), depth + 1)))
    .getOrElse(score)

3 Comments

I coudn't check it to compile because Tree type is not given. Probably had some typo somewhere. Can you provide type for Tree?
is possible to avoid cast on acc and h? acc.asInstanceOf[Double]?
You can refine type for fold like this: fold[Double](...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.