Scala partial tail recursion - scala

Because I am defining an interpreter with a lot of variables, I am writing this:
type Context = Map[String, Int]
abstract class Expr
case class Let(varname: String, varvalue: Expr, body: Expr) extends Expr
case class Var(name: String) extends Expr
case class Plus(a: Expr, b: Expr) extends Expr
case class Num(i: Int) extends Expr
def eval(expr: Expr)(implicit ctx: Context): Int = expr match {
case Let(i, e, b) => eval(b)(ctx + (i -> eval(e)))
case Var(s) => ctx(s)
case Num(i) => i
case Plus(a, b) => eval(a) + eval(b)
}
For very long expressions this fails because of StackOverflowException, for expressions of the type:
Let("a", 1,
Let("b", Plus("a", "a"),
Let("c", Plus("b", "a"),
Let("d", 1, ... )
However, once the value of a variable is defined, I just need to call the evaluator again on the body of the Let, it seems to me that it should just do some kind of partial tail-recursion.
How is it possible to achieve partial tail recursion in Scala?

You want some way of getting tail-call optimizations on only some of the branches of eval. I don't think this is possible - the most Scala will do is accept a #tailrec annotation to a method as a whole and fail at compile time if it can't optimize the method into a loop.
However, making this iterative to take advantage of the the tail-call with the Let is pretty straight forward:
def eval(expr: Expr, ctx: Context): Int = {
// The expression/context pair we try to reduce at every loop iteration
var exprM = expr;
var ctxM = ctx;
while (true) {
expr match {
case Var(s) => return ctxM(s)
case Num(i) => return i
case Plus(a, b) => return eval(a,ctxM) + eval(b,ctxM)
case Let(i, e, b) => {
ctxM += i -> eval(e,ctxM). // Update ctxM
exprM = b // Update exprM
}
}
}
return 0; // unreachable, but Scala complains otherwise I'm not returning 'Int'
}
Note this won't solve the stack overflows due to long chains of Pluss - there really isn't much we can do with those because the recursive calls are not in tail position.
There was a time I thought Scala would make some #tailcall annotation to deal with this sort of thing, but I am not sure there is that much interest in such things anymore.

You should avoid using return in scala. In this scenario you could use a flag for the while control.
e.g.
var result = Option.empty[Int]
while (result.isEmpty) {
...
result = ctxM(s)
...
}
result
There are also other (IMO better) ways to go about this. For example https://typelevel.org/cats/datatypes/freemonad.html

Related

Can I avoid using asInstanceOf in a pattern match when matching a stateful subclass object?

As I was modelling expressions like Var("x") or Number(7) and writing an eval function with pattern matching, I ran into a case where I could not avoid using the ´asInstanceOf` method.
2 restrictions
I do not want to avoid pattern matching by declaring an eval method in Expr and define it in its subclasses (cf. Expression problem, I prefer pattern match).
I also do not want something like Var("x", 7).
sealed trait Expr
object Expr {
def eval(e: Expr): Int = e match {
case Number(n) => n
case Var(_) => e.asInstanceOf[Var].getValue()
}
}
case class Number(n: Int) extends Expr
case class Var(s: String) extends Expr {
var value = 0
def getValue(): Int = value
def updateValue(x: Int): Unit = {
this.value = x
}
}
val x = Var("x")
x.updateValue(1)
Expr.eval(x) // 1
When I define the second case like this: case Var(x) => Var(x).getValue(), i get Expr.eval(x) // 0. This is, because Var(x) on the right side will construct a fresh Var with value 0.
I'm ok with using asInstanceOf but in the sense of improvement, I wonder if there is a cleaner solution than using asInstanceOf, which I haven't found yet.
You can use # to bind a variable to a pattern. Use it like this:
def eval(e: Expr): Int = e match {
case Number(n) => n
case v#Var(_) => v.getValue()
}
You can also check the type of a variable in a pattern match
def eval(e: Expr): Int = e match {
case Number(n) => n
case v: Var => v.getValue()
}

functional programming with scala

I've been trying to enhance my knowledge with scala.
I am trying to implement this function recursively but having difficulty.
My main question IS, how can you accept a list in the parameter that accepts either a list or numbers.
depth(x: Any): Int is the signature you want, then pattern match on x to determine if it's a List[_] or not, where _ indicates you don't care what's in the list. (Using Seq[_] would be the more idiomatic Scala type to use, actually.) Note that the example shown is missing a pair of parens, List(1, 2, List(3))... It also assumes that depth(8) == 0 (for example).
A tricky part is that you shouldn't assume that a nested list will either be the first or last element in the "parent" list, i.e., ...List(1,List(2,3),4)... is possible.
A final bit worth mentioning; if you were building a "production" depth method, it would be worth having a Tree abstraction with Node and Leaf concrete types so you can use a better type signature, depth(tree: Tree[_]): Int, to make it explicitly clear when something represents part of the tree structure vs. data in the tree. Using List here is convenient for the exercise, but a bit ambiguous otherwise, since you could have a tree of stuff where some nodes are actually lists.
I will try to answer this by giving a shot on the recursive solution:
def depth(listOrNum: Any): Int = {
def help(y: Any, c: Int): Int = {
y match {
case y: Int => c
case List(curHead, rest # _*) =>
Math.max(help(curHead, c+1), help(rest, c))
case _ => 0
}
}
help(listOrNum, 0)
}
collect is handy here:
def depth(xs: List[Any]): Int =
1 + xs.collect{case xs: List[_] => depth(xs)}
.foldLeft(0)(_ max _)
P.S. I agree with Dean's comments about the type List[Any] being a poor way to represent trees. List[Any] is a type that should never appear in ordinary Scala code, so I'm sad to see it used in an exercise intended for beginners.
If you are insisting on using for comprehension, I can provide implementation that works with it.
First you define two useful classes
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
class Folder[T](init : T, step : (T,T) => T) extends Builder[T,T] {
private[this] var state = init
override def += (elem : T) = {
state = step(state, elem)
this
}
override def clear() {
state = init
}
override def result() : T = state
}
class CanBuildFolder[F,T](init : T, step : (T,T) => T) extends CanBuildFrom[F,T,T] {
override def apply() : Builder[T,T] = new Folder(init, step)
override def apply(from : F) : Builder[T,T] = new Folder(init, step)
}
than you can use them with the for comprehension
import scala.math.max
object Test {
val example = List(1, List(2, 3), List( List(4, 5), 6, List(7, List(List(8), 9))))
implicit val maxFolder = new CanBuildFolder[List[Any], Int](0, max)
def depth(source : List[Any]) : Int =
for (x <- source) yield x match {
case l : List[Any] => depth(l) + 1
case _ => 1
}
assert(depth(example) == 5)
}

Scala: How to compute the sum of all elements in the leaves of a Binary Tree?

I'm learning Scala by working the exercises from the book "Scala for the Impatient". Given the following way to model binary trees with case classes, one question asks to compute the sum of all elements in the leaves.
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
case class Node(left: BinaryTree, right: BinaryTree) extends BinaryTree
My solution is as follows and works as expected. However, I'm using a MutableList and because Scala favors immutability, I am wondering if there's a way to solve the problem using List?
def leafSum(tree: BinaryTree): Int = {
collectLeaves(tree) { MutableList[Int]() }.sum
}
private def collectLeaves(tree: BinaryTree)(leaves: MutableList[Int]): MutableList[Int] = tree match {
case Node(left, right) =>
collectLeaves(left)(leaves); collectLeaves(right)(leaves)
case Leaf(value) => leaves += value
}
Using a List is not a good idea for the reason that when you concatenate two lists, you will have to copy their content so an O(n) complexity operation each time you encounter a Node.
If you really want to do it with Lists, you could do it like this:
def leafSum(tree: BinaryTree): Int = {
collectLeaves(tree).sum
}
private def collectLeaves(tree: BinaryTree): List[Int] = tree match {
case Node(left, right) => collectLeaves(left) ::: collectLeaves(right)
case Leaf(value) => List(value)
}
although in my opinion it's better to compute directly the sum as you don't need to store the values in the leaves:
def sum(tree: BinaryTree): Int = tree match {
case Node(left, right) => sum(left) + sum(right)
case Leaf(value) => value
}
Here's a recursive approach that doesn't use a helper method that I think is fairly elegant. Note it's not tail recursive and will run out of memory for large inputs.
def leafSum(tree: BinaryTree): Int = tree match{
case leaf:Leaf => leaf.value
case node:Node => leafSum(node.left) + leafSum(node.right)
}

Scala, pattern matching on a tuple of generic trait, checking if types are equal

I know a lot of questions exist about type erasure and pattern matching on generic types, but I could not understand what should I do in my case from answers to those, and I could not explain it better in title.
Following code pieces are simplified to present my case.
So I have a trait
trait Feature[T] {
value T
def sub(other: Feature[T]): Double
}
// implicits for int,float,double etc to Feature with sub mapped to - function
...
Then I have a class
class Data(val features: IndexedSeq[Feature[_]]) {
def sub(other: Data): IndexedSeq[Double] = {
features.zip(other.features).map {
case(e1: Feature[t], e2: Feature[y]) => e1 sub e2.asInstanceOf[Feature[t]]
}
}
}
And I have a test case like this
case class TestFeature(val value: String) extends Feature[String] {
def sub(other: Feature[String]): Double = value.length - other.length
}
val testData1 = new Data(IndexedSeq(8, 8.3f, 8.232d, TestFeature("abcd"))
val testData2 = new Data(IndexedSeq(10, 10.1f, 10.123d, TestFeature("efg"))
testData1.sub(testData2).zipWithIndex.foreach {
case (res, 0) => res should be (8 - 10)
case (res, 1) => res should be (8.3f - 10.1f)
case (res, 2) => res should be (8.232d - 10.123d)
case (res, 3) => res should be (1)
}
This somehow works. If I try sub operation with instances of Data that have different types in same index of features, I get a ClassCastException. This actually satisfies my requirements, but if possible I would like to use Option instead of throwing an exception. How can I make following code work?
class Data(val features: IndexedSeq[Feature[_]]) {
def sub(other: Data): IndexedSeq[Double] = {
features.zip(other.features).map {
// of course this does not work, just to give idea
case(e1: Feature[t], e2: Feature[y]) if t == y => e1 sub e2.asInstanceOf[Feature[t]]
}
}
}
Also I am really inexperienced in Scala, so I would like to get feedback on this type of structure. Are there another ways to do this and which way would make most sense?
Generics don't exist at runtime, and an IndexedSeq[Feature[_]] has forgotten what the type parameter is even at compile time (#Jatin's answer won't allow you to construct a Data with a list of mixed types of Feature[_]). The easiest answer might be just to catch the exception (using catching and opt from scala.util.control.Exception). But, to answer the question as written:
You could check the classes at runtime:
case (e1: Feature[t], e2: Feature[y]) if e1.value.getClass ==
e2.value.getClass => ...
Or include the type information in the Feature:
trait Feature[T] {
val value: T
val valueType: ClassTag[T] // write classOf[T] in subclasses
def maybeSub(other: Feature[_]) = other.value match {
case valueType(v) => Some(actual subtraction)
case _ => None
}
}
The more complex "proper" solution is probably to use Shapeless HList to preserve the type information in your lists:
// note the type includes the type of all the elements
val l1: Feature[Int] :: Feature[String] :: HNil = f1 :: f2 :: HNil
val l2 = ...
// a 2-argument function that's defined for particular types
// this can be applied to `Feature[T], Feature[T]` for any `T`
object subtract extends Poly2 {
implicit def caseFeatureT[T] =
at[Feature[T], Feature[T]]{_ sub _}
}
// apply our function to the given HLists, getting a HList
// you would probably inline this
// could follow up with .toList[Double]
// since the resulting HList is going to be only Doubles
def subAll[L1 <: HList, L2 <: HList](l1: L1, l2: L2)(
implicit zw: ZipWith[L1, L2, subtract.type]) =
l1.zipWith(l2)(subtract)
That way subAll can only be called for l1 and l2 all of whose elements match, and this is enforced at compile time. (If you really want to do Options you can have two ats in the subtract, one for same-typed Feature[T]s and one for different-typed Feature[_]s, but ruling it out entirely seems like a better solution)
You could do something like this:
class Data[T: TypeTag](val features: IndexedSeq[Feature[T]]) {
val t = implicitly[TypeTag[T]]
def sub[E: TypeTag](other: Data[E]): IndexedSeq[Double] = {
val e = implicitly[TypeTag[E]]
features.zip(other.features).flatMap{
case(e1, e2: Feature[y]) if e.tpe == t.tpe => Some(e1 sub e2.asInstanceOf[Feature[T]])
case _ => None
}
}
}
And then:
case class IntFeature(val value: Int) extends Feature[Int] {
def sub(other: Feature[Int]): Double = value - other.value
}
val testData3 = new Data(IndexedSeq(TestFeature("abcd")))
val testData4 = new Data(IndexedSeq(IntFeature(1)))
println(testData3.sub(testData4).zipWithIndex)
gives Vector()

How to define a ternary operator in Scala which preserves leading tokens?

I'm writing a code generator which produces Scala output.
I need to emulate a ternary operator in such a way that the tokens leading up to '?' remain intact.
e.g. convert the expression c ? p : q to c something. The simple if(c) p else q fails my criteria, as it requires putting if( before c.
My first attempt (still using c/p/q as above) is
c match { case(true) => p; case _ => q }
another option I found was:
class ternary(val g: Boolean => Any) { def |: (b:Boolean) = g(b) }
implicit def autoTernary (g: Boolean => Any): ternary = new ternary(g)
which allows me to write:
c |: { b: Boolean => if(b) p else q }
I like the overall look of the second option, but is there a way to make it less verbose?
Thanks
Even though the syntax doesn't evaluate in the expected order--it binds the conditional to the first option!--you can make your own ternary operator like this:
class IfTrue[A](b: => Boolean, t: => A) { def |(f: => A) = if (b) t else f }
class MakeIfTrue(b: => Boolean) { def ?[A](t: => A) = new IfTrue[A](b,t) }
implicit def autoMakeIfTrue(b: => Boolean) = new MakeIfTrue(b)
The trick is to interpret ? as a method on a MakeIfTrue object that binds the condition to the object to return in the "true" case. The resulting IfTrue object now uses the | method as a request to evaluate the condition, returning the stored true option if the condition is true, or the just-passed-in one if it's false.
Note that I've used stuff like => A instead of just A--by-name parameters--in order to not evaluate the expression unless it's actually used. Thus, you'll only evaluate the side that you actually need (just like an if statement).
Let's see it in action:
scala> List(1,3,2).isEmpty ? "Empty" | "Nonempty"
res0: java.lang.String = Nonempty
scala> (4*4 > 14) ? true | false
res1: Boolean = true
scala> class Scream(s: String) { println(s.toUpperCase + "!!!!") }
defined class Scream
scala> true ? new Scream("true") | new Scream("false")
TRUE!!!!
res3: Scream = Scream#1ccbdf7
(P.S. To avoid confusion with the Actor library ?, you probably ought to call it something else like |?.)
Let's keep it simple:
Java:
tmp = (a > b) ? a : b;
Scala:
tmp = if (a > b) a else b
Besides simplicity, it is clear and fast because: do not allocate objects you don't need, keeps the garbage collector out of equation (as it always should be) and makes better use of processor caches.
You could use something like this
sealed trait TernaryOperand[A] {
def >(q: => A): A
}
case class TernarySecond[A](val p: A) extends TernaryOperand[A] {
def >(q: => A) = p
}
case class TernaryThird[A]() extends TernaryOperand[A] {
def >(q: => A) = q
}
implicit def ternary(c: Boolean) = new {
def ?[A](p: => A): TernaryOperand[A] = if (c) TernarySecond(p) else TernaryThird()
}
val s1 = true ? "a" > "b"
println(s1) //will print "a"
val s2 = false ? "a" > "b"
println(s2) //will print "b"
This code converts any boolean value to an anonymous type that has a method called ?. Depending on the value of the boolean, this method will either return TernarySecond or TernaryThird. They both have a method called > which returns the second operand or the third one respectively.
Ternary operator which adds my improvement to the best of Rex Kerr’s and Michel Krämer’s implementations:
My improvement to use Scala’s new value class to avoid boxing overhead.
Call by-name on 2nd and 3rd operands so only the chosen one is evaluated.
Michel’s call by-value on the 1st (Boolean) operand to avoid by-name overhead; it is always evaluated.
Rex’s concrete class for the condition to avoid any anonymous class overhead.
Michel’s evaluation of the condition to determine which class to construct to avoid of overhead of a two argument constructor.
.
sealed trait TernaryResult[T] extends Any {
def |(op3: => T): T
}
class Ternary2ndOperand[T](val op2: T) extends AnyVal with TernaryResult[T] {
def |(op3: => T) = op2
}
class Ternary3rdOperand[T](val op2: T) extends AnyVal with TernaryResult[T] {
def |(op3: => T) = op3
}
class Ternary(val op1:Boolean) extends AnyVal {
def ?[A](op2: => A): TernaryResult[A] = if (op1) new Ternary2ndOperand(op2) else new Ternary3rdOperand(op2)
}
object Ternary {
implicit def toTernary(condition: Boolean) = new Ternary(condition)
}
Note the improvement over if else is not just the 6 characters saved. With Scala IDE’s syntax coloring on keywords being the same (e.g. purple) for if, else, null, and true, there is better contrast in some cases (which isn't shown by the syntax coloring below as currently rendered on this site):
if (cond) true else null
cond ? true | null