Skip to content

Instantly share code, notes, and snippets.

@cedricbastin
Last active August 29, 2015 14:18
Show Gist options
  • Save cedricbastin/a2aa1c81c92194b77cdf to your computer and use it in GitHub Desktop.
Save cedricbastin/a2aa1c81c92194b77cdf to your computer and use it in GitHub Desktop.
exploring lazy evaluation to avoid multiple passes over a tree
object Main extends App {
/*
* Exploring lazy evaluation in Scala to replace all nodes in a tree with the minimum value of the tree in 1 pass
* thanks to @begeric
*/
sealed trait Tree
case class Node(tl:Tree, v:Int, t2:Tree) extends Tree
case object Leaf extends Tree
/*
* we give a concrete tree as input and a lazy value min which will eventually contain the minimum of all nodes
* we will lazily construct a new Node which will use the minimum once available
*/
def minTree(tree:Tree):Tree = {
/*
* the min input is lazy as it will only be available after a first pass through the tree
* the result is a tuple such that we can return both the not yet constructed tree and the calculated minimum
*/
def rec(t: Tree, min: => Int):(() => Tree, Int) = {
t match {
case Node(tl, v, tr) =>
val l = rec(tl, min)
val r = rec(tr, min)
//the minima from both subnodes are available and are thus concrete
val cmin = Math.min(v, Math.min(l._2, r._2))
(() => Node(l._1(), min, r._1()), cmin)
case Leaf => (() => Leaf, Int.MaxValue) //initial empty acc
}
}
// as min is a recursive value it need a type
lazy val (res, min:Int) = rec(tree, min)
// evaluate the lazy tree as min is now available
res()
}
println(minTree(Node(Node(Node(Leaf, 2, Leaf), 1, Leaf), 3, Node(Leaf, 5, Leaf))))
}
@cedricbastin
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment