Scala pattern matching with async or future - scala

Example code snippet :
def evalExpr(e: Expr): Int = e match {
case Num(n) => n
case Sum(l, r) => evalExpr(l) + evalExpr(r)
case Prod(l, r) => evalExpr(l) * evalExpr(r)
}
What would be the best way to implement pattern matching where evalExpr runs asynchronously?

You can Wrap them in Scala's Futures :
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
trait Expr
case class Num(n:Int) extends Expr
case class Sum(n:Expr,m:Expr) extends Expr
case class Prod(n:Expr,m:Expr) extends Expr
def evalExpr(e: Expr): Future[Int] = e match {
case Num(n) => Future(n)
case Sum(l, r) =>
val exp1 = evalExpr(l)
val exp2 = evalExpr(r)
for{
i<-exp1
j<-exp2
} yield i + j
case Prod(l, r) =>
val exp1 = evalExpr(l)
val exp2 = evalExpr(r)
for{
i<-exp1
j<-exp2
} yield i + j
}
evalExpr(Prod(Sum(Num(1),Prod(Num(3),Num(2))),Num(2))).map(println)
scala> evalExpr(Prod(Sum(Num(1),Prod(Num(3),Num(2))),Num(2))).map(println)
8 // As you can see output of the calculation is asynchronously printed.
res0: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise#65039982

If the evalExpr(Expr) would return Future[Int] you would write for instance Prod(l, r) like this:
case Prod(l, r) => {
val eval1 = evalExpr(l)
val eval2 = evalExpr(r)
for {
left <- eval1
right <- eval2
} yield left*right
}
This would combine the two futures - left and right - together and return new future.
Using futures also the case Num(n) should be => Future(n).

Related

Can I generate Scala code from a template (of sorts)?

Can I generate Scala code from a template (of sorts)?
I know how to do this in Racket/Scheme/Lisp, but not in Scala. Is this something Scala macros can do?
I want to have a code template where X varies. If I had this code template:
def funcX(a: ArgsX): Try[Seq[RowX]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcX(t, a)}
case _ => Failure(new MissingThingException)
}
and tokens Apple and Orange, a macro would take my template, replace the Xs, and produce:
def funcApple(a: ArgsApple): Try[Seq[RowApple]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcApple(t, a)}
case _ => Failure(new MissingThingException)
}
def funcOrange(a: ArgsOrange): Try[Seq[RowOrange]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcOrange(t, a)}
case _ => Failure(new MissingThingException)
}
Try macro annotation with tree transformer
#compileTimeOnly("enable macro paradise")
class generate extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro GenerateMacro.impl
}
object GenerateMacro {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
val trees = List("Apple", "Orange").map { s =>
val transformer = new Transformer {
override def transform(tree: Tree): Tree = tree match {
case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" if tname.toString.contains("X") =>
val tname1 = TermName(tname.toString.replace("X", s))
val tparams1 = tparams.map(super.transform(_))
val paramss1 = paramss.map(_.map(super.transform(_)))
val tpt1 = super.transform(tpt)
val expr1 = super.transform(expr)
q"$mods def $tname1[..$tparams1](...$paramss1): $tpt1 = $expr1"
case q"${tname: TermName} " if tname.toString.contains("X") =>
val tname1 = TermName(tname.toString.replace("X", s))
q"$tname1"
case tq"${tpname: TypeName} " if tpname.toString.contains("X") =>
val tpname1 = TypeName(tpname.toString.replace("X", s))
tq"$tpname1"
case q"$expr.$tname " if tname.toString.contains("X") =>
val expr1 = super.transform(expr)
val tname1 = TermName(tname.toString.replace("X", s))
q"$expr1.$tname1"
case tq"$ref.$tpname " if tpname.toString.contains("X") =>
val ref1 = super.transform(ref)
val tpname1 = TypeName(tpname.toString.replace("X", s))
tq"$ref1.$tpname1"
case t => super.transform(t)
}
}
transformer.transform(annottees.head)
}
q"..$trees"
}
}
#generate
def funcX(a: ArgsX): Try[Seq[RowX]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcX(t, a)}
case _ => Failure(new MissingThingException)
}
//Warning:scalac: {
// def funcApple(a: ArgsApple): Try[Seq[RowApple]] = w.getThing() match {
// case Some((t # (_: Thing))) => w.wrap(t)(Detail.funcApple(t, a))
// case _ => Failure(new MissingThingException())
// };
// def funcOrange(a: ArgsOrange): Try[Seq[RowOrange]] = w.getThing() match {
// case Some((t # (_: Thing))) => w.wrap(t)(Detail.funcOrange(t, a))
// case _ => Failure(new MissingThingException())
// };
// ()
//}
Also you can try approach with type class
def func[A <: Args](a: A)(implicit ar: ArgsRows[A]): Try[Seq[ar.R]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.func(t, a)}
case _ => Failure(new MissingThingException)
}
trait ArgsRows[A <: Args] {
type R <: Row
}
object ArgsRows {
type Aux[A <: Args, R0 <: Row] = ArgsRows[A] { type R = R0 }
implicit val apple: Aux[ArgsApple, RowApple] = null
implicit val orange: Aux[ArgsOrange, RowOrange] = null
}
sealed trait Args
trait ArgsApple extends Args
trait ArgsOrange extends Args
trait Thing
sealed trait Row
trait RowApple extends Row
trait RowOrange extends Row
object Detail {
def func[A <: Args](t: Thing, a: A)(implicit ar: ArgsRows[A]): ar.R = ???
}
class MissingThingException extends Throwable
trait W {
def wrap[R <: Row](t: Thing)(r: R): Try[Seq[R]] = ???
def getThing(): Option[Thing] = ???
}
val w: W = ???
In my opinion, it looks like you could pass your funcX function as a higher-order function. You could also combine it with currying to make a "function factory":
def funcX[A](f: (Thing, A) => RowX)(a: A): Try[Seq[RowX]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){f(t,a)}
case _ => Failure(new MissingThingException)
}
Then you could use it to create instances of funcApple or funcOrange:
val funcApple: ArgsApple => Try[Seq[RowX]] = funcX(Detail.funcApple)
val funcOrange: ArgsOrange => Try[Seq[RowX]] = funcX(Detail.funcOrange)
funcApple(argsApple)
funcOrange(argsOrange)
I assumed the signature of Detail.funcApple and Detail.funcOrange is similar to (Thing, X) => RowX, but of course you could use different.
You may not actually need macros to achieve this, you can use a pattern match a generic type like this:
import scala.util.Try
def funcX[A](input :A) :Try[Seq[String]] = input match {
case x :String => Success(List(s"Input is a string: $input, call Detail.funcApple"))
case x :Int => Success(List(s"Input is an int, call Detail.funcOrange"))
}
scala> funcX("apple")
res3: scala.util.Try[Seq[String]] = Success(List(Input is a string: apple, call Detail.funcApple))
scala> funcX(11)
res4: scala.util.Try[Seq[String]] = Success(List(Input is an int, call Detail.funcOrange))

Creating a union on the left side of an Either type

Is there a way to bind a value of Either[L1, R1] to a function of type R1 => Either[L2, R2] and get a value of Either[L1 | L2, R2] so individual functions can declare and potentially return their errors and consumers of a monadic pipeline of these functions can cleanly handle all possible errors in an exhaustive, type-safe way?
Edit
Here's an example...
sealed trait IncrementError
case object MaximumValueReached extends IncrementError
def increment(n: Int): Either[IncrementError, Int] = n match {
case Integer.MAX_VALUE => Left(MaximumValueReached)
case n => Right(n + 1)
}
sealed trait DecrementError
case object MinimumValueReached extends DecrementError
def decrement(n: Int): Either[DecrementError, Int] = n match {
case Integer.MIN_VALUE => Left(MinimumValueReached)
case n => Right(n - 1)
}
for {
n <- increment(0).right
n <- decrement(n).right
} yield n // scala.util.Either[Object, Int] = Right(0)
With that return type I'm not able to do exhaustive error handling. I'm curious if there exists a way to do this using standard Scala Either or if there exists something in a library like scalaz which supports this behavior. I'd like to be able to handle errors like this...
val n = for {
n <- increment(0).right
n <- decrement(n).right
} yield n // scala.util.Either[IncrementError | DecrementError, Int]
match n {
case Left(MaximumValueReached) => println("Maximum value reached!")
case Left(MinimumValueReached) => println("Minimum value reached!")
case Right(_) => println("Success!")
}
I would do following:
/**
* Created by alex on 10/3/16.
*/
object Temp{
sealed trait IncrementError
case object MaximumValueReached extends IncrementError
sealed trait DecrementError
case object MinimumValueReached extends DecrementError
type MyResult = Either[Either[IncrementError, DecrementError], Int]
def increment(n: Int): MyResult = n match {
case Integer.MAX_VALUE => Left(Left(MaximumValueReached))
case n => Right(n + 1)
}
def decrement(n: Int): MyResult = n match {
case Integer.MIN_VALUE => Left(Right(MinimumValueReached))
case n => Right(n - 1)
}
def main(args:Array[String]) = {
val result = for {
k <- increment(0).right
n <- decrement(k).right
} yield n
result match {
case Left(Left(MaximumValueReached)) => println("Maximum value reached!")
case Left(Right(MinimumValueReached)) => println("Minimum value reached!")
case Right(_) => println("Success!")
}
}
}
Honestly I don't like it but it works for the case if you don't want to have IncrementError and DecrementError to inherit from some ancestor trait for some reasons.

pattern matching, static or dynamic binding

I wanted to know in a pattern matching, like in the following, do we say that the case classes are bound dynamically or statically?
sealed trait Expr
case class Lit(n: Int) extends Expr
case class Add(l: Expr, r: Expr) extends Expr
class Eval {
def eval(e: Expr): Int = e match {
case Lit(n) => n
case Add(l, r) => eval(l) + eval(r)
}
}
class Printo {
def printo(e: Expr): Unit = e match {
case Lit(n) => print(" " + n + " ")
case Add(l, r) => printo(l); print("+"); printo(r)
}
}
//Test
object TestExpr {
def main(args: Array[String]) {
val eval = new Eval
val printo = new Printo
val expr1 =
Add(Add(Lit(4), Add(Lit(7), Lit(10))),
Add(Lit(4), Add(Lit(7), Lit(10))))
val x = eval.eval(expr1)
p + "" + println(" = " + x)
}
}
How I can know if the Lit(n) or Add(l, r) are called / bound statically or dynamically?

How to stop Stream to evaluate next element and get accumulated result in a functional way

I have this code and I want to let Stream to stop iteration and also get the accumulated result. Basically, the iteration is based on errorLimit number
sealed trait Ele
case class FailureEle() extends Ele
case class SuccessEle() extends Ele
type EitherResult = Either[IndexedSeq[Ele], Seq[FailureEle]]
def parse(process: Process[Task, Ele], errorLimit: Int): EitherResult = {
val errorAccumulator = new ListBuffer[FailureEle]
val taskProcess = process.map(t => {
t match {
case x: FailureEle => errorAccumulator += x
case _ =>
}
t
}).takeWhile(_ => !(errorAccumulator.size == errorLimit))
val voSeq = taskProcess.runLog.run
if (errorAccumulator.isEmpty) {
Left(voSeq)
} else {
Right(errorAccumulator)
}
}
val result = Seq(FailureEle(), SuccessEle(), FailureEle(), SuccessEle(), SuccessEle(), FailureEle(), SuccessEle())
val adaptor = new SeqAdaptor[Ele](result)
val process: Process[Task, Ele] = Process
.repeatEval(Task {adaptor.next()}).takeWhile(t => !t.shouldStop).map(_.get)
parse(process, 1).isRight //no SuccessEle will be iterated
parse(process, 2).isRight //only one SuccessEle will be iterated
parse(process, 3).isRight //the last one SuccessEle will not be iterated
It is working, but there are several issues that I want to refactor the parse method to be more functional:
ListBuffer is an imperative way
takeWhile condition has no logic to check current element, it is still using ListBuffer result
so I wonder is there a tail recursion way to replace the imperative way by using ListBuffer.
scan may not be better enough, but works
sealed trait Ele
case class FailureEle(e: Throwable) extends Ele
case class SuccessEle(r: String) extends Ele
def parse(p: Process[Task, Ele], error: Int): Process[Task, (Seq[SuccessEle], Seq[FailureEle])] = {
p.scan(Seq[SuccessEle]() -> Seq[FailureEle]()) { (r, e) =>
val (s, f) = r
e match {
case fail: FailureEle =>
s -> (f :+ fail)
case succ: SuccessEle =>
(s :+ succ) -> f
}
}.dropWhile { case (succ, fail) => fail.size < error }.take(1)
}
def test() {
def randomFail = {
val nInt = scala.util.Random.nextInt()
println("getting" + nInt)
if(nInt % 5 == 0 )
FailureEle(new Exception("fooo"))
else
SuccessEle(nInt.toString)
}
val infinite = Process.repeatEval(Task.delay(randomFail))
val r = parse(infinite, 3).runLast.run
println(r)
}

Simplify expression in Scala

I have such case classes:
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: Int) extends Tree
Now i write such object :
object Main {
type Environment = String => Int
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(n) if (v == n) => Const(1)
case _ => Const(0)
}
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
def simple(t: Tree): Const = t match {
case Sum(l, r) if (l.isInstanceOf[Const] && r.isInstanceOf[Const]) => Const(l.asInstanceOf[Const].v + r.asInstanceOf[Const].v)
case Sum(l, r) if (l.isInstanceOf[Sum] && r.isInstanceOf[Sum]) => Const(simple(l).v+ simple(r).v)
case Sum(l, r) if (l.isInstanceOf[Sum]) => Const(simple(l).v + r.asInstanceOf[Const].v)
case Sum(l, r) if (r.isInstanceOf[Sum]) => Const(simple(r).v + l.asInstanceOf[Const].v)
}
def main(args: Array[String]) {
val exp: Tree = Sum(Sum(Var("x"), Var("x")), Sum(Const(7), Var("y")))
val env: Environment = {
case "x" => 5
case "y" => 7
}
println("Expression: " + exp)
println("Evaluation with x=5, y=7: " + eval(exp, env))
println("Derivative relative to x:\n " + derive(exp, "x"))
println("Derivative relative to y:\n " + derive(exp, "y"))
println("Simplified expression:\n" + simple(derive(exp, "x")))
}
}
I am new in scala. Is it possible write method simple with small count of code and maybe in scala way?
Thanks for advice.
You're almost there. In Scala, extractors can be nested:
def simple(t: Tree): Const = t match {
case Sum(Const(v1), Const(v2)) => Const(v1 + v2)
case Sum(s1 # Sum(_,_), s2 # Sum(_, _)) => Const(simple(s1).v+ simple(s2).v)
case Sum(s # Sum(_, _), Const(v)) => Const(simple(s).v + v)
case Sum(Const(v), s # Sum(_, _)) => Const(simple(s).v + v)
}
Of course, this will give you some warnings about incomplete matches, and the sx # Sum(_, _) repeatedly suggests that there may be a better approach that includes matching on Const and Var at the root level and making more recursive calls to simple.
Although this question has been closed, but I think this version should be a better one,
def simplify(t: Tree): Tree = t match {
case Sum(Const(v1), Const(v2)) => Const(v1 + v2)
case Sum(Const(v1), Sum(Const(v2), rr)) => simplify(Sum(Const(v1 + v2), simplify(rr)))
case Sum(l, Const(v)) => simplify(Sum(Const(v), simplify(l)))
case Sum(l, Sum(Const(v), rr)) => simplify(Sum(Const(v), simplify(Sum(l, rr))))
case Sum(Sum(ll, lr), r) => simplify(Sum(ll, simplify(Sum(lr, r))))
case Sum(Var(n), r) => Sum(simplify(r), Var(n))
case _ => t
}
it seems works with "complex" expressions with variables.
Just a small improvement:
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(`v`) => Const(1)
case _ => Const(0)
}
How about this:
def simplify(t: Tree): Tree = t match {
case Sum(Const(v1),Const(v2)) => Const(v1+v2)
case Sum(left,right) => simplify(Sum(simplify(left),simplify(right)))
case _ => t //Not necessary, but for completeness
}
Note that it returns a Tree, not a Const, so it should be able to simplify trees with variables too.
I'm learning Scala so any suggestions as to why this wouldn't work etc. are more than welcome :-)
EDIT: Just discovered that the second case causes an infinite loop when using variables. Substitute it with:
case Sum(left,right) => Sum(simplify(left),simplify(right))
Unfortunately this breaks when left and right return Const, which could be simplified even further (e.g. Sum(Const(2),Const(3))).