Last active
December 19, 2016 04:34
-
-
Save Centaur/96771ea0cff73d620aaf6f1b6d2d240c to your computer and use it in GitHub Desktop.
Tailrec to Fold
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.snippets | |
import scala.collection.immutable.Stream.#:: | |
import scala.util.{Failure, Success, Try} | |
class InsufficientParametersException(message: String) extends RuntimeException(message) | |
object Tailrec2Fold { | |
type RpnModel = String | |
type CalculationState = (String, String) | |
def calculate(model: RpnModel, first: String, second: String): CalculationState = { | |
println("Confirm short circuit:" + (model, first, second)) | |
if (model == "m5") { | |
throw new InsufficientParametersException("Error") | |
} else ("[" + model + "-" + first, ":" + second + "-" + model + "]") | |
} | |
def loop(rpnModels: List[RpnModel], state: CalculationState): CalculationState = { | |
rpnModels match { | |
case Nil => state | |
case head :: tail => | |
try { | |
loop(tail, calculate(head, state._1, state._2)) | |
} catch { | |
case ex: InsufficientParametersException => println(ex.getMessage); state | |
} | |
} | |
} | |
def loopFold(rpnModels: List[RpnModel], state: CalculationState): CalculationState = { | |
def folder: List[Try[CalculationState]] = rpnModels.foldLeft(Try(state) :: Nil) { (accu, nextModel) => | |
accu match { | |
case Success(s) :: _ => Try(calculate(nextModel, s._1, s._2)) :: accu | |
case Failure(e) :: tail => println(e.getMessage); return tail | |
} | |
} | |
folder.head.get | |
} | |
def loopStream(rpnModels: List[RpnModel], state: CalculationState): CalculationState = { | |
lazy val stateStream:Stream[Try[CalculationState]] = Success(state) #:: stateStream.zip(rpnModels).map { | |
case (Success(s), model) => Try(calculate(model, s._1, s._2)) | |
} | |
stateStream.takeWhile(_.isSuccess).last.get | |
} | |
val modelSuccess = List("m1", "m2", "m3", "m4") | |
val modelFailure = List("m1", "m5", "m3", "m4") | |
val stateFixture: CalculationState = ("s1", "s2") | |
def main(args: Array[String]): Unit = { | |
assert(loop(modelSuccess, stateFixture) == loopFold(modelSuccess, stateFixture)) | |
println("===================") | |
assert(loop(modelFailure, stateFixture) == loopFold(modelFailure, stateFixture)) | |
println("===================") | |
assert(loop(modelSuccess, stateFixture) == loopStream(modelSuccess, stateFixture)) | |
println("===================") | |
assert(loop(modelFailure, stateFixture) == loopStream(modelFailure, stateFixture)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment