Unifying Oo and Functional Programming Jorge Ortiz
Unifying Oo and Functional Programming Jorge Ortiz
Jorge Ortiz
CS94SI
“Scala goes further than all other well-
known languages in fusing object-
oriented and functional programming.”
• Main goals:
• Abstraction
• Code reuse
• Unifying data and behavior
• Controlling complexity
What is OOP?
• Case classes
• Scala’s version of algebraic data types
• Extractors
• A way for pattern matching to cohabit
with OO data abstraction
Extractors
object Polar {
def unapply(z: Cart):
Option[(Double, Double]) =
...
}
Cart(1, 1) match {
case Polar(r, th) => ...
// r == sqrt(2), th == Pi / 4
}
Extractors
• Provide user-defined views on objects
• Defined with an unapply method in a
singleton object (usually the companion
object for a class, but not necessarily so)
• Decouples types from pattern matching
• Allows pattern matching to cohabit with
data abstraction – extractor can provide
same view despite implementation changes
Functions as Objects,
Objects as Functions
Functions
• Functions in Scala:
• Inherit from the FunctionN trait
(where N is number of arguments)
trait Set[A]
extends (A => Boolean) ...
Array
class Array[A]
extends PartialFunction[Int, A] ...
Syntactic Sugar
EMail(“jorge”, “gmail.com”)
// == “jorge@gmail.com"
Apply
case class Cartesian(x: Double, y: Double)
object Polar {
def unapply...
def apply(r: Double, th: Double):
Cartesian =
Cartesian(r * cos(th), r * sin(th))
}
Polar(sqrt(2), Pi/4)
// == Cartesian(1.0, 1.0)
Functions +
Scala Compiler
val square = (x: Int) => x*x
square(2)
Functions +
Scala Compiler
val square = (x: Int) => x*x
square(2)
Functions +
Scala Compiler
val square = new Function1[Int, Int] {
def apply(x: Int): Int = x*x
}
square(2)
Functions +
Scala Compiler
val square = new Function1[Int, Int] {
def apply(x: Int): Int = x*x
}
square(2)
Functions +
Scala Compiler
val square = new Function1[Int, Int] {
def apply(x: Int): Int = x*x
}
square.apply(2)
Functions +
Scala Compiler
val square = new Function1[Int, Int] {
def apply(x: Int): Int = x*x
}
square.apply(2)
Functions +
Scala Compiler
Function1<Integer, Integer> square =
new Function1<Integer, Integer> {
public Integer apply(Integer x) {
return x*x;
}
}
square.apply(2)
Functions +
Scala Compiler
val square = (x: Int) => x*x
square(2)
Functions +
Scala Compiler
val filter =
(c: List[A], p: A => Boolean) =>
...
Functions +
Scala Compiler
println(“Goodbye, world!”)
println(pi)
println(“Goodbye, world!”)
println(pi)
// Prints: ???
// ???
// ???
Lazy Evaluation
lazy val pi = {
println(“Hello, world!”)
3.14159
}
println(“Goodbye, world!”)
println(pi)
println(pi)
println(pi)
// Prints: ???
// ???
// ???
Lazy Evaluation
lazy val pi = {
println(“Hello, world!”)
3.14159
}
println(pi)
println(pi) // pi got cached, not
// evaluated again
// Prints: Hello, world!
// 3.14159
// 3.14159
Lazy C/C++/Java?
• C, C++, and Java have short-circuit
evaluation
• a && b
• b only gets evaluated if a is true
• a || b
• b only gets evaluated if a is false
Lazy C/C++/Java?
• C, C++, and Java also have if/then, while, for
if (condition) {
block
}
var i = 0 // print: 0
myWhile(i < 10) { // 1
println(i) // 2
i = i + 1 // 3
} // ...
while
def myWhile(cond: => Boolean)(block: => Unit): Unit = {
if (cond) {
block
myWhile(cond)(block)
}
}
var i = 11
myWhile(i < 10) {
println(i) // prints nothing
i = i + 1
}