Getting Functional with Scala
An Introduction to Functional Programming and the Scala Programming Language
September, 2016
2
Software Engineer at IBM Mobile Innovation Lab
@jorgelpaez19
Jorge Paez
3
My IBM Journey… So far
www-01.ibm.com/employment/us/extremeblue https://www.ibm.com/innovation/milab/
4
Where will yours start?
http://www-03.ibm.com/employment/entrylevel_campus.html
5
What is Functional Programming?
6
Function Not a Function
7
Core Ideas
• Data is immutable
• PURE function are our basic building block
• Use expressions over instructions
• First class functions
• Type-strictness
8
…but why?
9
Benefits!
• Simpler concurrency/parallelism
• Optimizations with caching or memoization
• Easier debugging
• Cleaner/less verbose code
• Encourages code re-use
• Promotes Test Driven Development
10
Pure vs Impure
// In Main.java
public String getFormal(String name) {

name = "Mr." + name;

return name;

}
// In Main.scala
def getFormal(name: String) = s"Mr. $name!"
11
Expressions vs Instructions
// In Main.java
public double[] convertToMeters(double[] measurements) {

double[] metricMeasurements = 

new double[measurements.length];



for(int i = 0; i < measurements.length; ++i) {

metricMeasurements[i] =

measurements[i] * CONVERSION_FACTOR;

}



return metricMeasurements;

}
// In Main.scala
def convertToMeters(measurements: Seq[Double]) =

measurements.map(n => n * CONVERSION_FACTOR)
12
First Class Functions
def main(args: Array[String]): Unit = {

draw(getCurve(0, 90), 1)

draw(getCurve, 2)

}



def getCurve: Double => Seq[(Double, Double)] =

(r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))



def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =

(r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))



def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =

((r * Math.cos(theta)), (r * Math.sin(theta)))





def draw(func: Double => Seq[(Double, Double)], scale: Double)
13
First Class Functions
def main(args: Array[String]): Unit = {

draw(getCurve(0, 90), 1)

draw(getCurve, 2)

}



def getCurve: Double => Seq[(Double, Double)] =

(r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))



def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =

(r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))



def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =

((r * Math.cos(theta)), (r * Math.sin(theta)))





def draw(func: Double => Seq[(Double, Double)], scale: Double)




def getCurve: Double => Seq[(Double, Double)] =

(r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))



def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =

(r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))







14
First Class Functions
def main(args: Array[String]): Unit = {

draw(getCurve(0, 90), 1)

draw(getCurve, 2)

}



def getCurve: Double => Seq[(Double, Double)] =

(r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))



def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =

(r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))



def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =

((r * Math.cos(theta)), (r * Math.sin(theta)))





def draw(func: Double => Seq[(Double, Double)], scale: Double)


def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =

((r * Math.cos(theta)), (r * Math.sin(theta)))



15
First Class Functions
def main(args: Array[String]): Unit = {

draw(getCurve(0, 90), 1)

draw(getCurve, 2)

}



def getCurve: Double => Seq[(Double, Double)] =

(r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))



def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =

(r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))



def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =

((r * Math.cos(theta)), (r * Math.sin(theta)))





def draw(func: Double => Seq[(Double, Double)], scale: Double)
def main(args: Array[String]): Unit = {

draw(getCurve(0, 90), 1)

draw(getCurve, 2)

}





def draw(func: Double => Seq[(Double, Double)], scale: Double)
16
First Class Functions
def main(args: Array[String]): Unit = {

draw(getCurve(0, 90), 1)

draw(getCurve, 2)

}



def getCurve: Double => Seq[(Double, Double)] =

(r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))



def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =

(r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))



def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =

((r * Math.cos(theta)), (r * Math.sin(theta)))





def draw(func: Double => Seq[(Double, Double)], scale: Double)
17
Type Strictness
sealed trait Person



case class Student(name: String) extends Person



case class Alumni(name: String) extends Person



def getBusFare(person : Person): Int = {

person match {

case p: Student => 0

case p: Alumni => 2

}

}
18
Options
// Form asking for person's gender

// a) Female

// b) Male

// c) Don’t want to disclose



def main(args: Array[String]): Unit = {

val answers = Seq(Some("Female"), Some("Male"), Some(null), None)



answers.map(a => a match {

case Some(gender) =>

if(gender == null){

"the didn't want to disclose his or her gender"

} else {

s"The user's gender is $gender"

}

case None => "the user didn't pick a value on the form"

})

}
19
What’s next?
20
Keep Learning
• Slides: http://www.slideshare.net/JorgePaez15/getting-functional-with-scala
• Deploying a Scala server to Bluemix: https://www.ibm.com/innovation/milab/how-
to-run-a-scala-web-app-on-ibm-bluemix/
• Free class: https://www.coursera.org/learn/progfun1
Thank You

@jorgelpaez19
@IBM_MIL

Getting Functional with Scala

  • 1.
    Getting Functional withScala An Introduction to Functional Programming and the Scala Programming Language September, 2016
  • 2.
    2 Software Engineer atIBM Mobile Innovation Lab @jorgelpaez19 Jorge Paez
  • 3.
    3 My IBM Journey…So far www-01.ibm.com/employment/us/extremeblue https://www.ibm.com/innovation/milab/
  • 4.
    4 Where will yoursstart? http://www-03.ibm.com/employment/entrylevel_campus.html
  • 5.
  • 6.
  • 7.
    7 Core Ideas • Datais immutable • PURE function are our basic building block • Use expressions over instructions • First class functions • Type-strictness
  • 8.
  • 9.
    9 Benefits! • Simpler concurrency/parallelism •Optimizations with caching or memoization • Easier debugging • Cleaner/less verbose code • Encourages code re-use • Promotes Test Driven Development
  • 10.
    10 Pure vs Impure //In Main.java public String getFormal(String name) {
 name = "Mr." + name;
 return name;
 } // In Main.scala def getFormal(name: String) = s"Mr. $name!"
  • 11.
    11 Expressions vs Instructions //In Main.java public double[] convertToMeters(double[] measurements) {
 double[] metricMeasurements = 
 new double[measurements.length];
 
 for(int i = 0; i < measurements.length; ++i) {
 metricMeasurements[i] =
 measurements[i] * CONVERSION_FACTOR;
 }
 
 return metricMeasurements;
 } // In Main.scala def convertToMeters(measurements: Seq[Double]) =
 measurements.map(n => n * CONVERSION_FACTOR)
  • 12.
    12 First Class Functions defmain(args: Array[String]): Unit = {
 draw(getCurve(0, 90), 1)
 draw(getCurve, 2)
 }
 
 def getCurve: Double => Seq[(Double, Double)] =
 (r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))
 
 def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =
 (r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))
 
 def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =
 ((r * Math.cos(theta)), (r * Math.sin(theta)))
 
 
 def draw(func: Double => Seq[(Double, Double)], scale: Double)
  • 13.
    13 First Class Functions defmain(args: Array[String]): Unit = {
 draw(getCurve(0, 90), 1)
 draw(getCurve, 2)
 }
 
 def getCurve: Double => Seq[(Double, Double)] =
 (r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))
 
 def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =
 (r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))
 
 def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =
 ((r * Math.cos(theta)), (r * Math.sin(theta)))
 
 
 def draw(func: Double => Seq[(Double, Double)], scale: Double) 
 
 def getCurve: Double => Seq[(Double, Double)] =
 (r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))
 
 def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =
 (r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))
 
 
 

  • 14.
    14 First Class Functions defmain(args: Array[String]): Unit = {
 draw(getCurve(0, 90), 1)
 draw(getCurve, 2)
 }
 
 def getCurve: Double => Seq[(Double, Double)] =
 (r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))
 
 def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =
 (r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))
 
 def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =
 ((r * Math.cos(theta)), (r * Math.sin(theta)))
 
 
 def draw(func: Double => Seq[(Double, Double)], scale: Double) 
 def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =
 ((r * Math.cos(theta)), (r * Math.sin(theta)))
 

  • 15.
    15 First Class Functions defmain(args: Array[String]): Unit = {
 draw(getCurve(0, 90), 1)
 draw(getCurve, 2)
 }
 
 def getCurve: Double => Seq[(Double, Double)] =
 (r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))
 
 def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =
 (r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))
 
 def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =
 ((r * Math.cos(theta)), (r * Math.sin(theta)))
 
 
 def draw(func: Double => Seq[(Double, Double)], scale: Double) def main(args: Array[String]): Unit = {
 draw(getCurve(0, 90), 1)
 draw(getCurve, 2)
 }
 
 
 def draw(func: Double => Seq[(Double, Double)], scale: Double)
  • 16.
    16 First Class Functions defmain(args: Array[String]): Unit = {
 draw(getCurve(0, 90), 1)
 draw(getCurve, 2)
 }
 
 def getCurve: Double => Seq[(Double, Double)] =
 (r) => (0 to 360).map(theta => getCartesianCoordinates(r, theta))
 
 def getCurve(thetaO: Int, thetaF: Int): Double => Seq[(Double, Double)] =
 (r) => (thetaO to thetaF).map(theta => getCartesianCoordinates(r, theta))
 
 def getCartesianCoordinates(r: Double, theta: Double): (Double, Double) =
 ((r * Math.cos(theta)), (r * Math.sin(theta)))
 
 
 def draw(func: Double => Seq[(Double, Double)], scale: Double)
  • 17.
    17 Type Strictness sealed traitPerson
 
 case class Student(name: String) extends Person
 
 case class Alumni(name: String) extends Person
 
 def getBusFare(person : Person): Int = {
 person match {
 case p: Student => 0
 case p: Alumni => 2
 }
 }
  • 18.
    18 Options // Form askingfor person's gender
 // a) Female
 // b) Male
 // c) Don’t want to disclose
 
 def main(args: Array[String]): Unit = {
 val answers = Seq(Some("Female"), Some("Male"), Some(null), None)
 
 answers.map(a => a match {
 case Some(gender) =>
 if(gender == null){
 "the didn't want to disclose his or her gender"
 } else {
 s"The user's gender is $gender"
 }
 case None => "the user didn't pick a value on the form"
 })
 }
  • 19.
  • 20.
    20 Keep Learning • Slides:http://www.slideshare.net/JorgePaez15/getting-functional-with-scala • Deploying a Scala server to Bluemix: https://www.ibm.com/innovation/milab/how- to-run-a-scala-web-app-on-ibm-bluemix/ • Free class: https://www.coursera.org/learn/progfun1
  • 21.