I am learning scala from Coursera. I cannot understand the following slide on the limitations of object-oriented decomposition
Can you please simplify this for me? What is being said here? If this is not the proper way to ask this question kindly guide me on how to make it better. But, this is all there is. I do not understand this slide. Looking for someone to help me make sense of it
I guess they mean that this rule can be easily implemented in FP with pattern matching using nested patterns
sealed trait Expression
case class Lit(value: Int) extends Expression
case class Add(expr1: Expression, expr2: Expression) extends Expression
case class Mult(expr1: Expression, expr2: Expression) extends Expression
def simplify(expr: Expression): Expression = expr match {
case Add(Mult(a, b), Mult(a1, c)) if a == a1 => Mult(a, Add(b, c))
case _ => expr
}
But how to implement it easily in OOP style?
sealed trait Expression {
def simplify: Expression
}
case class Lit(value: Int) extends Expression {
override def simplify: Expression = ???
}
case class Add(expr1: Expression, expr2: Expression) extends Expression {
override def simplify: Expression = ???
}
case class Mult(expr1: Expression, expr2: Expression) extends Expression {
override def simplify: Expression = ???
}
Well, actually it can be implemented using visitor pattern (double/multiple dispatch, emulating multi-methods)
sealed trait Expression {
def simplify: Expression
def simplifyAdd(that: Expression): Expression
def simplifyAddLit(lit: Lit): Expression
def simplifyAddAdd(add: Add): Expression
def simplifyAddMult(mult: Mult): Expression
}
case class Lit(value: Int) extends Expression {
override def simplify: Expression = this
override def simplifyAdd(that: Expression): Expression = that.simplifyAddLit(this)
override def simplifyAddLit(lit: Lit): Expression = Add(lit, this)
override def simplifyAddAdd(add: Add): Expression = Add(add, this)
override def simplifyAddMult(mult: Mult): Expression = Add(mult, this)
}
case class Add(expr1: Expression, expr2: Expression) extends Expression {
override def simplify: Expression = expr1.simplifyAdd(expr2)
override def simplifyAdd(that: Expression): Expression = that.simplifyAddAdd(this)
override def simplifyAddLit(lit: Lit): Expression = Add(lit, this)
override def simplifyAddAdd(add: Add): Expression = Add(add, this)
override def simplifyAddMult(mult: Mult): Expression = Add(mult, this)
}
case class Mult(expr1: Expression, expr2: Expression) extends Expression {
override def simplify: Expression = this
override def simplifyAdd(that: Expression): Expression = that.simplifyAddMult(this)
override def simplifyAddLit(lit: Lit): Expression = Add(lit, this)
override def simplifyAddAdd(add: Add): Expression = Add(add, this)
override def simplifyAddMult(mult: Mult): Expression =
if (mult.expr1 == expr1) Mult(expr1, Add(mult.expr2, expr2))
else Add(mult, this)
}
or
sealed trait Expression {
def simplify: Expression
def simplifyAdd(that: Expression): Expression
def simplifyAddMult(mult: Mult): Expression
}
case class Lit(value: Int) extends Expression {
override def simplify: Expression = this
override def simplifyAdd(that: Expression): Expression = Add(this, that)
override def simplifyAddMult(mult: Mult): Expression = Add(mult, this)
}
case class Add(expr1: Expression, expr2: Expression) extends Expression {
override def simplify: Expression = expr1.simplifyAdd(expr2)
override def simplifyAdd(that: Expression): Expression = Add(this, that)
override def simplifyAddMult(mult: Mult): Expression = Add(mult, this)
}
case class Mult(expr1: Expression, expr2: Expression) extends Expression {
override def simplify: Expression = this
override def simplifyAdd(that: Expression): Expression = that.simplifyAddMult(this)
override def simplifyAddMult(mult: Mult): Expression =
if (mult.expr1 == expr1) Mult(expr1, Add(mult.expr2, expr2))
else Add(mult, this)
}
What if we want to make simplify
recursive?