shaktimaan - 1 year ago 51

Scala Question

I am learning the concepts of pattern matching in Scala. Following is an exercise for the same. The task is to define a show function that outputs an expression as a

`String`

`object Test {`

trait Expr

case class Number(n: Int) extends Expr

case class Sum(e1: Expr, e2: Expr) extends Expr

case class Prod(e1: Expr, e2: Expr) extends Expr

case class Var(name: String) extends Expr

def nestOperations(e1: Expr, e2: Expr): String = {

val l = e1 match {

case Number(n) => n.toString

case Prod(x, y) => nestOperations(x, y)

case Var(s) => s

case Sum(x, y) => "(" + show(x) + " + " + show(y) + ")"

}

val r = e2 match {

case Number(n) => n.toString

case Prod(x, y) => nestOperations(x, y)

case Var(s) => s

case Sum(x, y) => "(" + show(x) + " + " + show(y) + ")"

}

l + " * " + r

}

def show(e: Expr): String = e match {

case Number(n) => n.toString

case Sum(e1, e2) => show(e1) + " + " + show(e2)`

case Prod(e1, e2) => nestOperations(e1, e2)

case Var(s) => s

}

show(Sum(Number(1), Number(2)))

show(Sum(Prod(Number(2), Var("x")), Var("y")))

show(Prod(Sum(Number(2), Var("x")), Var("y")))

}

The expectation is that:

`show(Sum(Number(1), Number(2)))`

`1 + 2`

`show(Sum(Prod(Number(2), Var("x")), Var("y")))`

`2 * x + y`

`show(Prod(Sum(Number(2), Var("x")), Var("y")))`

`(2 + x) * y`

The program achieves all of the above. I want to know if the

`nestOperations`

Answer Source

You're right. That repeated code in `nestOperations()`

can be eliminated.

```
def nestOperations(es: Expr*): String =
es.map {
case Number(n) => n.toString
case Prod(x, y) => nestOperations(x, y)
case Var(s) => s
case Sum(x, y) => "(" + show(x) + " + " + show(y) + ")"
}.mkString(" * ")
```

But why stop there? You can pull much the same stunt with `show()`

and eliminate `nestOperations()`

altogether.

```
def show(es: Expr*): String = es.map{
case Number(n) => n.toString
case Sum(e1, e2) => if (es.length > 1) "(" + show(e1) + " + " + show(e2) + ")"
else show(e1) + " + " + show(e2)
case Prod(e1, e2) => show(e1, e2)
case Var(s) => s
}.mkString(" * ")
```