Getting Functional with Scala An Introduction to Functional Programming and the Scala Programming Language September, 2016
Getting Functional with Scala An Introduction to Functional Programming and the Scala Programming Language
September, 2016
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
7
Core Ideas• Data is immutable
• PURE function are our basic building block • Use expressions over instructions • First class functions • Type-strictness
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 Personcase class Student(name: String) extends Personcase class Alumni(name: String) extends Persondef 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 disclosedef 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" }) }
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