/*
(Functional) Data representation in Scala
A few syntax basics:
*/
// we define a class (called Point)
// we define the constructor for the class:
// Point(1,2)
class Point(x: Int, y: Int){
def xVal:Int = x
def yVal:Int = y
// checks if a point is higher on the y axis than our current point
// higher is method of the class Point
def higher(p: Point): Boolean =
p.yVal > y
override def toString : String =
s"({},{})"
}
val p = new Point(1,2)
p.higher(new Point(2,3))
new Point(2,1) // this is an expression that evaluates to an object
new Point(2,1) == new Point(2,1) // evaluates to FALSE
// classes in Scala are VERY similar to those in Java
/*
Traits in Scala are VERY similar to Java interfaces
*/
trait FTree {
/* why do we not define methods, such as
isEmpty and size as MEMBERS of FTree?
is it possible? (YES)
*/
}
case object FEmpty extends FTree {}
case class FNode(key: Int, left: FTree, right: FTree) extends FTree {}
FEmpty == FEmpty // should return true
val t1 = FNode(7,
FNode(1,FEmpty,FEmpty),
FNode(2,FEmpty,FEmpty))
/*
We have created several identical object called FEmpty previously
We would like to have a single object instead of 4
We can use the "object" keyword.
*/
FNode(1,FEmpty,FEmpty) == FNode(1,FEmpty,FEmpty) // will return true
/* How to we DECOMPOSE or "LOOK INTO" objects?
* using pattern matching
* */
def isEmpty(t: FTree): Boolean =
t match {
case FNode(_,_,_) => false
case FEmpty => true
//case _ => false
}
def size(t: FTree): Int =
t match{
case FEmpty => 0
case FNode(_,left,right) => 1 + size(left) + size(right)
}
/* ANOTHER implementation of Trees
which is structurally equivalent, but the type
is differently organised.
*/
trait OOTree {
def isEmpty: Boolean
def size: Int
}
case object OOEmpty extends OOTree {
override def isEmpty: Boolean = true
override def size: Int = 0
}
case class OONode (key: Int, left: OOTree, right: OOTree) extends OOTree {
override def isEmpty: Boolean = false
override def size: Int = 1 + left.size + right.size
}
val t2 = OONode(7,
OONode(1,OOEmpty,OOEmpty),
OONode(2,OOEmpty,OOEmpty))
/*
* What is the difference between: FTree and OOTree?
*
* isEmpty and size are MEMBERS of OOTree while
* ----- || ------ are just function of FTree
*
* THE FIRST IMPLEMEMENTATION (FTree), relies on
* pattern-matching, to DECOMPOSE the object
*
* THE SND IMPL. (OOTree), uses "methods"
* */
t2.isEmpty
t2.size
trait Expr {
def eval: Int
}
case class Val(i: Int) extends Expr{
override def eval:Int = i
}
case class Add(left: Expr, right: Expr) extends Expr {
override def eval: Int = left.eval + right.eval
}
case class Mult(left: Expr, right: Expr) extends Expr {
override def eval: Int = left.eval * right.eval
}
val e = Add(Val(2),Mult(Val(3),Val(4)))
e.eval