I am learning Scala and want to know, what is preferred style of writing a function for a trait.
First:
sealed trait Expression
final case class Addition(left: Expression, right: Expression) extends Expression
final case class Subtraction(left: Expression, right: Expression) extends Expression
final case class Division(left: Expression, right: Expression) extends Expression
final case class SquareRoot(value: Expression) extends Expression
final case class Number(value: Double) extends Expression
object Expression {
def eval(e: Expression): Calculation =
e match {
case Addition(l1, r1) => eval(l1) match {
case Failure(rea1) => Failure(rea1)
case Success(res1) => eval(r1) match {
case Failure(rea2) => Failure(rea2)
case Success(res2) => Success(res1 + res2)
}
}
case Subtraction(l1, r1) => eval(l1) match {
case Failure(rea1) => Failure(rea1)
case Success(res1) => eval(r1) match {
case Failure(rea2) => Failure(rea2)
case Success(res2) => Success(res1 - res2)
}
}
case Division(l1, r1) => eval(r1) match {
case Failure(rea2) => Failure(rea2)
case Success(res2) => res2 match {
case 0.0 => Failure("Division by zero")
case _ => eval(l1) match {
case Failure(rea1) => Failure(rea1)
case Success(res1) => Success(res1 / res2)
}
}
}
case SquareRoot(v) => eval(v) match {
case Failure(rea) => Failure(rea)
case Success(res) => res match {
case x if x < 0 => Failure("Square root of negative number")
case y => Success(math.sqrt(y))
}
}
case Number(v) => Success(v)
}
}
Second:
sealed trait Expression {
def eval: Calculation =
this match {
case Addition(l, r) =>
l.eval match {
case Failure(reason) => Failure(reason)
case Success(r1) =>
r.eval match {
case Failure(reason) => Failure(reason)
case Success(r2) => Success(r1 + r2)
}
}
case Subtraction(l, r) =>
l.eval match {
case Failure(reason) => Failure(reason)
case Success(r1) =>
r.eval match {
case Failure(reason) => Failure(reason)
case Success(r2) => Success(r1 - r2)
}
}
case Division(l, r) =>
l.eval match {
case Failure(reason) => Failure(reason)
case Success(r1) =>
r.eval match {
case Failure(reason) => Failure(reason)
case Success(r2) =>
if(r2 == 0)
Failure("Division by zero")
else
Success(r1 / r2)
}
}
case SquareRoot(v) =>
v.eval match {
case Success(r) => if(r < 0)
Failure("Square root of negative number")
else
Success(Math.sqrt(r))
case Failure(reason) => Failure(reason)
}
case Number(v) => Success(v)
}
}
final case class Addition(left: Expression, right: Expression) extends Expression
final case class Subtraction(left: Expression, right: Expression) extends Expression
final case class Division(left: Expression, right: Expression) extends Expression
final case class SquareRoot(value: Expression) extends Expression
final case class Number(value: Int) extends Expression
Calculation, which is returned fromeval? \$\endgroup\$