SlideShare a Scribd company logo
LEARNING
 FUNCTIONAL
PROGRAMMING
   WITHOUT
 GROWING A
  NECKBEARD
   by Kelsey Innis / @kelseyinnis
HI!
                    I'm Kelsey.
I work at StackMob writing code that lets our users
 create & manage their applications, APIs, and data
  through the browser. I use Scala and the Lift web
               framework to do that.
WHY ARE YOU HERE?
http://www.youtube.com/embed/Lb8BCl6NKn0
To learn to write code with drive that don't take no
                        jive.
THE PAM GRIER CRITERIA FOR
     CODE BADASSERY
   Code, like Pam Grier, should be:
          Powerful,
          Beautiful, and
          Tough to mess with.
POWERFUL
Do big things
Do them easily
Do them quickly
TOUGH TO MESS WITH
Secure from outside manipulation
Hard to unintentionally make mistakes
Easy to maintain
BEAUTIFUL
Elegant, concise, and--yes--readable
Able to be easily reused
Fun to write
SCALA!
don't need parentheses for method calls
semicolons are optional
return value is the last line of the method
static typing with type inference
BUT WHAT DOES IT LOOK LIKE?
val   x: String = "a"
val   y = 2
val   z = 15.3
val   myThing = new Thing
val   theList = List("this", "sure", "is", "a", "list")
val   whatIsIt = theList(4)
BUT WHAT DOES IT LOOK LIKE?
def haggle(theirPrice: Int, myOffer: Int): String = {
        val theResponse: String =
                if (theirPrice <= myOffer + 5) {
                         "You've got a deal!"
                } else {
                         "I definitely wouldn't pay more than " +
                         (myOffer + (theirPrice - myOffer)/2) +
                         " for it."
                }
        theResponse
}

val askingPrice = 100
val iWantToPay = 50
val letsMakeADeal = haggle(askingPrice, iWantToPay)
FUNCTIONAL
PROGRAMMING
WHAT IS FUNCTIONAL
  PROGRAMMING?
  Well, what is a program?
ASK A KID
 (OR SIMPLE ENGLISH WIKIPEDIA)




                 A computer
               program is a list




WRONG
                of instructions
                   that tell a
              computer what to
                      do.
Imperative programming:
a sequence of commands that the computer carries
                 out in sequence

          Object-oriented programming:
these instructions, and the data they manipulate, are
                organized into objects
If a program's not a series of commands, then
                  what is it?
Learning Functional Programming Without Growing a Neckbeard
“Functional programming is a style of
 programming that emphasizes the
evaluation of expressions rather than
    the execution of commands.”
   —comp.lang.functional FAQ
WHAT THINGS ARE
val theQueen = "Elizabeth II"



                          but also...
def theGovernor(state: State) = {
        val candidates = state.getCandidates
        candidates(getTopVoteGetter)
}
WHAT IS A FUNCTION?



          A function is a relation
          between values where
          each of its input values
          gives back exactly one
           output value, playa.
SOME FUNCTIONS
Math.sqrt(x)
Collections.max(list)
Arrays.copyOf(original, newLength)
String.valueOf(anInt)
A function is pure if “the impact of a function on the
rest of the program [can] be described only in terms of
   its return type, and...the impact of the rest of the
program on the function be described only in terms of
            its arguments”. (Victor Nicollet)
This is our building block.




          Sooooo....
FUNCTIONS ARE DETERMINISTIC.
You will always get the same result if you run them
                with the same data.
             correctness is more clear
             unit tests are a breeze
             debugging is more directed

                    tough to mess with
FUNCTIONS ARE ENCAPSULATED.
“With a referentially transparent function, the interface-
     level activity is all one needs to know about its
            behavior.”. (Michael O. Church)
                        readability
                        reuse
                        maintainability

                           beautiful


                       tough to mess with
FUNCTIONS ARE COMMUTATIVE.
val firstThing = doOneThing()
val secondThing = doAnotherThing()

val thirdThing = doTheLastThing(firstThing, secondThing)



                        parallelization
                        concurrency
                        lazy evaluation

                                powerful
DATA IS IMMUTABLE.
Once an object is created, it cannot be changed.
If you need to change an object, make your own
                     copy.
                    a quick detour back to Java...

String s1 = "san dimas high school football rules"
String s2 = s1.toUpperCase

println("string 1: " + s1);
println("string 2: " + s2);



                       concurrency
                       rollback of data
                       simplicity

          powerful                               tough to mess with
Functions are deterministic
Functions are encapsulated
Functions are commutative
Data is immutable
                              Let's build.
...how?
FUNCTIONS AS FIRST CLASS CITIZENS
FIRST CLASS CITIZENS
val longSkinnyThing: String = "this is a string"
val listOfThem: List[String] = List("yarn","twine","thread")
val freshNewLongSkinnyThing: String = spinFromFiber("wool")
tieInAKnot(longSkinnyThing)




 class Rope(type:String) {
    override def toString(): String = "You've put me on a diet!";
}

val longSkinnyThing: Rope = new Rope("nautical")
val listOfThem: List[String] =
    List(longSkinnyThing, new Rope("climbing"),
    new Rope("clothesline"), new Rope("jump"))
val freshNewLongSkinnyThing: Rope = spinFromFiber("hemp")
tieInAKnot(longSkinnyThing)
val addSpam: (String) => String =
        { (x:String) => x + " and Spam" }
addSpam("Egg and Bacon")
        //result: "Egg and Bacon and Spam"
val menuOptions = List(addSpam, withoutSpam)
menuOptions(1)("Egg and Bacon and Spam")
        //result: "You can't have that"




   addSpam's type is (String) => String
(list of parameters' types) => return
                 type
RETURNING FUNCTIONS FROM
             FUNCTIONS
def tagText(tag: String, text: String) = "<" + tag +">" + text +
""
val noReally = tagText("em", "pay attention!!!!")
        //result: <em>pay attention!!!!</em>

def tagText2(tag: String) = { (text:String) =>"<" + tag +">" + te
xt + "" }
val tagWithAndSpam = tagText2("andSpam")
val breakfast = tagWithAndSpam("Spam Bacon and Sausage")
        //result: <andSpam>Spam Bacon and Sausage</andSpam>




                               beautiful


                                powerful
CURRYING




  YUM!
HIGHER-ORDER FUNCTIONS
FOR LOOP
                               Java

public void talkAboutFruit {
         Fruit[] fruits = {
                 new Fruit("apple"),
                 new Fruit("cherry"),
                 new Fruit("strawberry")
         };
         for (int i = 0; i < fruits.length; i++) {
                 System.out.println("Hey the other day I ate a " +
  fruits[i];
         }
}

                               Scala

 def talkAboutFruit = {
        val fruits = List(new Fruit("apple"),
                          new Fruit("cherry"),
                          new Fruit("strawberry"))
        for (i <- 0 until fruits.length) {
                System.out.println("Hey the other day I ate a " +
 fruits(i);
        }
}
LET'S GET ABSTRACT
    a function that takes a list and a function
          (list of parameters' types) => return type

  foreach(fruitList:List(fruits),
theFunction: (Fruit) => Unit): Unit
  def foreach(fruitList:List(fruits), theFunction: (Fruit) => Unit
) = {
         for (i <- 0 until fruitList.length) {
                 theFunction(fruits(i))
         }
}

 def talkAboutFruit = {
        val fruits = List(new Fruit("apple"),
                          new Fruit("cherry"),
                          new Fruit("strawberry"))
        val tellEm =
                { (f:Fruit) => System.out.println(
                        "Hey the other day I ate a " + f) }
        foreach(fruits, tellEm)
        }
}
MORE ABSTRACTERER!
foreach(theList:List(A), theFunction:
         (A) => Unit): Unit
abstract class Collection[A] {
        ...
        def foreach(theFunction: (A) => Unit): Unit
        ...
}

 def talkAboutFruit = {
        val fruits = List(new Fruit("apple"),
                          new Fruit("cherry"),
                          new Fruit("strawberry"))
        val tellEm =
                { (f:Fruit) => System.out.println(
                        "Hey the other day I ate a " + f) }
        fruits.foreach(tellEm)
        }
}
THIS:
abstract class Collection[A] {
        ...
        def foreach(theFunction: (A) => Unit): Unit = {
                for (i <- 0 until this.length) {
                        theFunction(this(i))
                }
        }
        ...
}


        IS NOT HOW SCALA
      IMPLEMENTED FOREACH
                          tough to mess with


                                powerful
SOMETHING A LITTLE JUICIER
def makePies: List[Pie] = {
        val fruits = List(new Fruit("apple"),
                          new Fruit("cherry"),
                          new Fruit("strawberry"))
        var pies = List()
        for (i <- 0 until fruits.length) {
                new Pie(fruits(i)) :: pies
        }
        pies
}


           on a collection of A, you can
        map(theFunction: (A) => B):
                 Collection[B]
def makePies: List[Pie] = {
        val fruits = List(new Fruit("apple"),
                          new Fruit("cherry"),
                          new Fruit("strawberry"))
        val makePie = { (f: Fruit) => new Pie(f) }
        fruits.map(makePie)
}
ANONYMOUS FUNCTIONS
val kindOfFruit: String = "blueberry"
val blueberryFruit = new Fruit(kindOfFruit)
val alsoBlueberry = new Fruit("blueberry")

val makePie = { (f: Fruit) => new Pie(f) }
fruits.map(makePie)
//equivalent to
fruits.map( { (f: Fruit) => new Pie(f) } )

def makePies: List[Pie] = {
        val fruits = List(new Fruit("apple"),
                          new Fruit("cherry"),
                          new Fruit("strawberry"))
        fruits.map( { (f: Fruit) => new Pie(f) } )
}

def makePies(fruits: List[Fruit]) : List[Pie]
         = fruits.map( { (f: Fruit) => new Pie(f) } )




                               beautiful
COLLECTION HANDLING
                            FILTER
val theList = List(new Fruit("apple"), new Fruit("pear"), new Fru
it("cherry"), new Fruit("strawberry"), new Fruit("honeydew"))

scala> theList.filter( { (f: Fruit) => f.isDelicious } )
res0: List[Fruit] = List(apple, cherry, strawberry)

                             FOLD
scala> theList.fold("The fruits on this list are: ")( { (stringSo
Far: String, f: Fruit) => stringSoFar + " " + f.name } )
res1: String = "The fruits on this list are: apple pear cherry st
rawberry honeydew"

                           REDUCE
scala> theList.fold(0)( { (count: Int, f: Fruit) => count + " " +
 f.totalPieces } )
res2: Int = 42300

theList.reduce( { (f: Fruit) => f.totalPieces } )
res3: Int = 42300
NESTED FOR-LOOPS
  def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]):
List(Serving[Pie, IceCream]) {
         val servings = List[Serving[Pie,IceCream]]()
         for (p <- 0 until pies.length) {
                  for (i <- 0 until iceCreams.length) {
                          val serving = new Serving(p, i)
                          serving :: servings
                  }
         }
         servings
}

  def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]):
List(Serving[Pie, IceCream]) {
         pies.map( { (p: Pie) =>
                 iceCreams.map( { (i: IceCream) =>
                         new Serving(p, i)
                 } )
         } )
}
IS THIS AN IMPROVEMENT?
def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]): L
ist(Serving[Pie, IceCream]) {
        val servingsLists =
                pies.map( { (p: Pie) =>
                        iceCreams.map( { (i: IceCream) =>
                                new Serving(p, i)
                        } )
                } )
        servingsLists.flatten
}
FUNCTION COMPOSITION




  def bakeAPie(f: Fruit, c: Crust): Pie
  def eatAPie(p: Pie): HappyKelsey

  def bakeAndEatAPie(f: Fruit, c: Crust): HappyKelsey = eatAPie com
  pose bakeAPie
          //could also be written bakeAPie andThen eatAPie


flatten compose map is flatMap, and it's MAGIC
FOR-YIELD
  def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]):
List(Serving[Pie, IceCream]) {
         for {
                 p <- pies
                 i <- iceCreams
         } yield {
                 new Serving(p,i)
         }
}




                               beautiful!
FUN WITH FOR-YIELD
  def goodPairings(pies: List[Pie], iceCreams: List[IceCream]): Li
st(Serving[Pie, IceCream]) {
         for {
                 p <- pies
                 i <- iceCreams
                 val serving = new Serving(p,i)
                 if (serving.isGood)
         } yield {
                 serving
         }
}

  def pleaseEverybody(audience: List[Person], pies: List[Pie], ice
Creams: List[IceCream]): List(ThankYou) {
         for {
                 person <- audience
                 p <- pies
                 i <- iceCreams
                 val serving = new Serving(p,i)
                 if (serving.isGood)
         } yield {
                 person.feed(serving)
         }
}
partial application
higher order functions
function composition
for-yield
AND NOW FOR SOMETHING
(NOT REALLY) COMPLETELY DIFFERENT
NULL.
YUCK
 public Serving<Pie, IceCream> serveBestALaMode(Pie key, Map<Pie,
 IceCream> pairings) {
     if(pairings != null) {
         IceCream iceCream = pairings.get(key);
         if(iceCream != null) {
             return new Serving(key, iceCream)
         } else {
                  return null;
         }
     }
 }


SCALA PROGRAMMING DOESN'T USE NULL.
              YIPPEE!
OPTION
Option[T] is either a Some with a value of type T
     inside, or None representing nothing.
 val someOption: Option[String] = Some("this is a value")
 val noneOption: Option[String] = None

 val theSomeValue = someOption.get //returns "this is a value"
 val someIsDefined = someOption.isDefined //returns true

 val theNoneValue = noneOption.get //throws NoSuchElementException
 val someIsDefined = someOption.isDefined //returns false
def serveBestALaMode(key: Pie, pairings: Map[Pie, IceCream]): Op
tion[Serving[Pie,IceCream]] = {
         iceCream: Option[IceCream] = pairings.get(key);
         if (iceCream.isDefined) {
                  Some(new Serving(key, iceCream.get))
         } else {
                  None
         }
}
OPTION IS KIND OF LIKE A
          COLLECTION
                             .MAP
someOption.map( {(str:String) => str + " SAN DIMAS HIGH SCHOOL FO
OTBALL RULES"} )
        //returns Some("this is a value SAN DIMAS HIGH SCHOOL FOO
TBALL RULES")
noneOption.map( {(str:String) => str + " SAN DIMAS HIGH SCHOOL FO
OTBALL RULES"} )
        //returns None

                          .FLATMAP
val favoritePie: Option[Pie] = Some(rhubarb)
favoritePie.map({ (pie: Pie) => pairings.get(pie) })
        //returns Some(Some(butterPecan))--whoops!
favoritePie.flatMap( { (pie: Pie) => pairings.get(pie) } )
        //returns Some(butterPecan)

                            .FILTER
val todaysSpecial: Option[Pie]
val myOrder = todaysSpecial.filter( { (pie: Pie) => (pie != butte
rPecan) }
FOR-YIELD OVER OPTION
 for {
         pie <- todaysSpecial
         bestIceCream <- pairings.get(pie)
         iceCream <- availableFlavors.get(bestIceCream) } yield {
         myDessert
}




                                beautiful


                                 powerful


                           tough to mess with
OPTION IS A MONAD
   WHAT IS A MONAD?
"Let’s look at what it is that makes Thing a monad.
The first thing is that I can wrap up a value inside of a
new Thing...We have a function of type A => Thing; a
  function which takes some value and wraps it up
                    inside a new Thing.
  We also have this fancy bind function, which digs
   inside our Thing and allows a function which we
supply to use that value to create a new Thing. Scala
             calls this function “flatMap“....
 What’s interesting here is the fact that bind is how
 you combine two things together in sequence. We
 start with one thing and use its value to compute a
                        new thing."
                    —Daniel Spiewak
FLATMAP IS MAGIC
 flatMap hides our boilerplate. For Lists, it abstracts
away a for-loop, letting us create a new List from an
   existing list. For Options, it abstracts away a null
check, letting us create a new nullable value from an
                       existing one.


                      tough to mess with
OTHER MONADS
accumulating errors
a cursor position in a database or file
states in a state machine
an environment that changes

                 powerful
EXTRA CREDIT WHOA




A SEMICOLON IS A MONAD
partial application
higher order functions
function composition
for-yield
monads
THE PSYCHOLOGY OF
FUNCTIONAL PROGRAMMING
READABILITY
“Is Clojure code hard to understand? Imagine if every
   time you read Java source code and encountered
   syntax elements like if statements, for loops, and
   anonymous classes, you had to pause and puzzle
  over what they mean. There are certain things that
    must be obvious to a person who wants to be a
  productive Java developer. Likewise there are parts
   of Clojure syntax that must be obvious for one to
    efficiently read and understand code. Examples
 include being comfortable with the use of let, apply,
 map, filter, reduce and anonymous functions...”—R.
                     Mark Volkmann
DSLS
class HelloWorldSpec extends Specification {

      "The 'Hello world' string" should {
        "contain 11 characters" in {
          "Hello world" must have size(11)
        }
        "start with 'Hello'" in {
          "Hello world" must startWith("Hello")
        }
        "end with 'world'" in {
          "Hello world" must endWith("world")
        }
      }
  }

                             from specs2
PURITY




“The truth is that good programmers mix the styles quite
   a bit. We program imperatively when needed, and
   functionally when possible.” - Michael O. Church
THANK YOU

More Related Content

PDF
Functional programming in Scala
PPT
Introduction to Functional Programming in JavaScript
PPTX
Functional Programming in JavaScript by Luis Atencio
PDF
Functional Programming Patterns (BuildStuff '14)
PDF
Functional Programming in Scala
PDF
Demystifying functional programming with Scala
PDF
Ankara Jug - Practical Functional Programming with Scala
PDF
Intro to Functional Programming
Functional programming in Scala
Introduction to Functional Programming in JavaScript
Functional Programming in JavaScript by Luis Atencio
Functional Programming Patterns (BuildStuff '14)
Functional Programming in Scala
Demystifying functional programming with Scala
Ankara Jug - Practical Functional Programming with Scala
Intro to Functional Programming

What's hot (18)

PDF
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
PDF
Introduction to programming in scala
PDF
Pragmatic Real-World Scala (short version)
PPTX
Joy of scala
PDF
One Monad to Rule Them All
PPTX
Intro to Functional Programming in Scala
PDF
Programming in Scala: Notes
PDF
Introduction to functional programming (In Arabic)
PDF
Functional Programming Patterns for the Pragmatic Programmer
PDF
Introduction to functional programming using Ocaml
PDF
A taste of Functional Programming
PDF
Refactoring Functional Type Classes
PDF
An introduction to property based testing
PDF
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
PPT
Introduction To Functional Programming
PDF
Twins: Object Oriented Programming and Functional Programming
PPTX
Functional Programming in Javascript - IL Tech Talks week
PDF
FP in Java - Project Lambda and beyond
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Introduction to programming in scala
Pragmatic Real-World Scala (short version)
Joy of scala
One Monad to Rule Them All
Intro to Functional Programming in Scala
Programming in Scala: Notes
Introduction to functional programming (In Arabic)
Functional Programming Patterns for the Pragmatic Programmer
Introduction to functional programming using Ocaml
A taste of Functional Programming
Refactoring Functional Type Classes
An introduction to property based testing
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Introduction To Functional Programming
Twins: Object Oriented Programming and Functional Programming
Functional Programming in Javascript - IL Tech Talks week
FP in Java - Project Lambda and beyond
Ad

Viewers also liked (20)

PDF
Functional programming with Xtend
PDF
Why Haskell
DOCX
1 4 vamos a jugar
PDF
Kerry Karl | Debunking Myths: GLUTEN
PPTX
Ratpack - SpringOne2GX 2015
PDF
5 Reasons Why Your Headlines Are On Life Support
PDF
Auktuálne otázky zodpovednosti za porušovanie práv duševného vlastníctva online
PPTX
Historia insp manuel antonio leal chacon
PPTX
Nuevas tecnologías de
PPTX
基隆交點Vol.5 - 王珈琳 - 陪伴,一段服務的時間
PPTX
Impacto de las tics en la educaciòn
PDF
8th biosimilars congregation 2016
PDF
Future of Grails
PDF
Grafico diario del dax perfomance index para el 11 02-2013
PPTX
Collaboration friday
PPT
부용
PPTX
leonardo monsalve
PDF
Brexit Webinar Series 3
DOCX
Planificacion de eliana caballero
PDF
rhythm workshop
Functional programming with Xtend
Why Haskell
1 4 vamos a jugar
Kerry Karl | Debunking Myths: GLUTEN
Ratpack - SpringOne2GX 2015
5 Reasons Why Your Headlines Are On Life Support
Auktuálne otázky zodpovednosti za porušovanie práv duševného vlastníctva online
Historia insp manuel antonio leal chacon
Nuevas tecnologías de
基隆交點Vol.5 - 王珈琳 - 陪伴,一段服務的時間
Impacto de las tics en la educaciòn
8th biosimilars congregation 2016
Future of Grails
Grafico diario del dax perfomance index para el 11 02-2013
Collaboration friday
부용
leonardo monsalve
Brexit Webinar Series 3
Planificacion de eliana caballero
rhythm workshop
Ad

Similar to Learning Functional Programming Without Growing a Neckbeard (20)

PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
A Prelude of Purity: Scaling Back ZIO
PDF
(How) can we benefit from adopting scala?
PPTX
Scala for curious
PDF
From Java to Scala - advantages and possible risks
PDF
Introduction to Scala
PDF
The Death of Final Tagless
PDF
An Introduction to Scala (2014)
PPTX
PPTX
Functional Programming
PDF
Introduction To Scala
PPTX
Intro to scala
PPTX
Lambda functions in java 8
PPT
SDC - Einführung in Scala
PPTX
Functional programming
PPTX
ZIO: Powerful and Principled Functional Programming in Scala
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
A Prelude of Purity: Scaling Back ZIO
(How) can we benefit from adopting scala?
Scala for curious
From Java to Scala - advantages and possible risks
Introduction to Scala
The Death of Final Tagless
An Introduction to Scala (2014)
Functional Programming
Introduction To Scala
Intro to scala
Lambda functions in java 8
SDC - Einführung in Scala
Functional programming
ZIO: Powerful and Principled Functional Programming in Scala

Recently uploaded (20)

PPTX
Cloud computing and distributed systems.
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Encapsulation theory and applications.pdf
PDF
Electronic commerce courselecture one. Pdf
PDF
cuic standard and advanced reporting.pdf
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Big Data Technologies - Introduction.pptx
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Machine learning based COVID-19 study performance prediction
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Cloud computing and distributed systems.
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Chapter 3 Spatial Domain Image Processing.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Encapsulation theory and applications.pdf
Electronic commerce courselecture one. Pdf
cuic standard and advanced reporting.pdf
Reach Out and Touch Someone: Haptics and Empathic Computing
Big Data Technologies - Introduction.pptx
Understanding_Digital_Forensics_Presentation.pptx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Empathic Computing: Creating Shared Understanding
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Machine learning based COVID-19 study performance prediction
Building Integrated photovoltaic BIPV_UPV.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows

Learning Functional Programming Without Growing a Neckbeard

  • 1. LEARNING FUNCTIONAL PROGRAMMING WITHOUT GROWING A NECKBEARD by Kelsey Innis / @kelseyinnis
  • 2. HI! I'm Kelsey. I work at StackMob writing code that lets our users create & manage their applications, APIs, and data through the browser. I use Scala and the Lift web framework to do that.
  • 3. WHY ARE YOU HERE? http://www.youtube.com/embed/Lb8BCl6NKn0 To learn to write code with drive that don't take no jive.
  • 4. THE PAM GRIER CRITERIA FOR CODE BADASSERY Code, like Pam Grier, should be: Powerful, Beautiful, and Tough to mess with.
  • 5. POWERFUL Do big things Do them easily Do them quickly
  • 6. TOUGH TO MESS WITH Secure from outside manipulation Hard to unintentionally make mistakes Easy to maintain
  • 7. BEAUTIFUL Elegant, concise, and--yes--readable Able to be easily reused Fun to write
  • 8. SCALA! don't need parentheses for method calls semicolons are optional return value is the last line of the method static typing with type inference
  • 9. BUT WHAT DOES IT LOOK LIKE? val x: String = "a" val y = 2 val z = 15.3 val myThing = new Thing val theList = List("this", "sure", "is", "a", "list") val whatIsIt = theList(4)
  • 10. BUT WHAT DOES IT LOOK LIKE? def haggle(theirPrice: Int, myOffer: Int): String = { val theResponse: String = if (theirPrice <= myOffer + 5) { "You've got a deal!" } else { "I definitely wouldn't pay more than " + (myOffer + (theirPrice - myOffer)/2) + " for it." } theResponse } val askingPrice = 100 val iWantToPay = 50 val letsMakeADeal = haggle(askingPrice, iWantToPay)
  • 12. WHAT IS FUNCTIONAL PROGRAMMING? Well, what is a program?
  • 13. ASK A KID (OR SIMPLE ENGLISH WIKIPEDIA) A computer program is a list WRONG of instructions that tell a computer what to do.
  • 14. Imperative programming: a sequence of commands that the computer carries out in sequence Object-oriented programming: these instructions, and the data they manipulate, are organized into objects
  • 15. If a program's not a series of commands, then what is it?
  • 17. “Functional programming is a style of programming that emphasizes the evaluation of expressions rather than the execution of commands.” —comp.lang.functional FAQ
  • 18. WHAT THINGS ARE val theQueen = "Elizabeth II" but also... def theGovernor(state: State) = { val candidates = state.getCandidates candidates(getTopVoteGetter) }
  • 19. WHAT IS A FUNCTION? A function is a relation between values where each of its input values gives back exactly one output value, playa.
  • 21. A function is pure if “the impact of a function on the rest of the program [can] be described only in terms of its return type, and...the impact of the rest of the program on the function be described only in terms of its arguments”. (Victor Nicollet)
  • 22. This is our building block. Sooooo....
  • 23. FUNCTIONS ARE DETERMINISTIC. You will always get the same result if you run them with the same data. correctness is more clear unit tests are a breeze debugging is more directed tough to mess with
  • 24. FUNCTIONS ARE ENCAPSULATED. “With a referentially transparent function, the interface- level activity is all one needs to know about its behavior.”. (Michael O. Church) readability reuse maintainability beautiful tough to mess with
  • 25. FUNCTIONS ARE COMMUTATIVE. val firstThing = doOneThing() val secondThing = doAnotherThing() val thirdThing = doTheLastThing(firstThing, secondThing) parallelization concurrency lazy evaluation powerful
  • 26. DATA IS IMMUTABLE. Once an object is created, it cannot be changed. If you need to change an object, make your own copy. a quick detour back to Java... String s1 = "san dimas high school football rules" String s2 = s1.toUpperCase println("string 1: " + s1); println("string 2: " + s2); concurrency rollback of data simplicity powerful tough to mess with
  • 27. Functions are deterministic Functions are encapsulated Functions are commutative Data is immutable Let's build.
  • 29. FUNCTIONS AS FIRST CLASS CITIZENS
  • 30. FIRST CLASS CITIZENS val longSkinnyThing: String = "this is a string" val listOfThem: List[String] = List("yarn","twine","thread") val freshNewLongSkinnyThing: String = spinFromFiber("wool") tieInAKnot(longSkinnyThing) class Rope(type:String) { override def toString(): String = "You've put me on a diet!"; } val longSkinnyThing: Rope = new Rope("nautical") val listOfThem: List[String] = List(longSkinnyThing, new Rope("climbing"), new Rope("clothesline"), new Rope("jump")) val freshNewLongSkinnyThing: Rope = spinFromFiber("hemp") tieInAKnot(longSkinnyThing)
  • 31. val addSpam: (String) => String = { (x:String) => x + " and Spam" } addSpam("Egg and Bacon") //result: "Egg and Bacon and Spam" val menuOptions = List(addSpam, withoutSpam) menuOptions(1)("Egg and Bacon and Spam") //result: "You can't have that" addSpam's type is (String) => String (list of parameters' types) => return type
  • 32. RETURNING FUNCTIONS FROM FUNCTIONS def tagText(tag: String, text: String) = "<" + tag +">" + text + "" val noReally = tagText("em", "pay attention!!!!") //result: <em>pay attention!!!!</em> def tagText2(tag: String) = { (text:String) =>"<" + tag +">" + te xt + "" } val tagWithAndSpam = tagText2("andSpam") val breakfast = tagWithAndSpam("Spam Bacon and Sausage") //result: <andSpam>Spam Bacon and Sausage</andSpam> beautiful powerful
  • 35. FOR LOOP Java public void talkAboutFruit { Fruit[] fruits = { new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry") }; for (int i = 0; i < fruits.length; i++) { System.out.println("Hey the other day I ate a " + fruits[i]; } } Scala def talkAboutFruit = { val fruits = List(new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry")) for (i <- 0 until fruits.length) { System.out.println("Hey the other day I ate a " + fruits(i); } }
  • 36. LET'S GET ABSTRACT a function that takes a list and a function (list of parameters' types) => return type foreach(fruitList:List(fruits), theFunction: (Fruit) => Unit): Unit def foreach(fruitList:List(fruits), theFunction: (Fruit) => Unit ) = { for (i <- 0 until fruitList.length) { theFunction(fruits(i)) } } def talkAboutFruit = { val fruits = List(new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry")) val tellEm = { (f:Fruit) => System.out.println( "Hey the other day I ate a " + f) } foreach(fruits, tellEm) } }
  • 37. MORE ABSTRACTERER! foreach(theList:List(A), theFunction: (A) => Unit): Unit abstract class Collection[A] { ... def foreach(theFunction: (A) => Unit): Unit ... } def talkAboutFruit = { val fruits = List(new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry")) val tellEm = { (f:Fruit) => System.out.println( "Hey the other day I ate a " + f) } fruits.foreach(tellEm) } }
  • 38. THIS: abstract class Collection[A] { ... def foreach(theFunction: (A) => Unit): Unit = { for (i <- 0 until this.length) { theFunction(this(i)) } } ... } IS NOT HOW SCALA IMPLEMENTED FOREACH tough to mess with powerful
  • 39. SOMETHING A LITTLE JUICIER def makePies: List[Pie] = { val fruits = List(new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry")) var pies = List() for (i <- 0 until fruits.length) { new Pie(fruits(i)) :: pies } pies } on a collection of A, you can map(theFunction: (A) => B): Collection[B] def makePies: List[Pie] = { val fruits = List(new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry")) val makePie = { (f: Fruit) => new Pie(f) } fruits.map(makePie) }
  • 40. ANONYMOUS FUNCTIONS val kindOfFruit: String = "blueberry" val blueberryFruit = new Fruit(kindOfFruit) val alsoBlueberry = new Fruit("blueberry") val makePie = { (f: Fruit) => new Pie(f) } fruits.map(makePie) //equivalent to fruits.map( { (f: Fruit) => new Pie(f) } ) def makePies: List[Pie] = { val fruits = List(new Fruit("apple"), new Fruit("cherry"), new Fruit("strawberry")) fruits.map( { (f: Fruit) => new Pie(f) } ) } def makePies(fruits: List[Fruit]) : List[Pie] = fruits.map( { (f: Fruit) => new Pie(f) } ) beautiful
  • 41. COLLECTION HANDLING FILTER val theList = List(new Fruit("apple"), new Fruit("pear"), new Fru it("cherry"), new Fruit("strawberry"), new Fruit("honeydew")) scala> theList.filter( { (f: Fruit) => f.isDelicious } ) res0: List[Fruit] = List(apple, cherry, strawberry) FOLD scala> theList.fold("The fruits on this list are: ")( { (stringSo Far: String, f: Fruit) => stringSoFar + " " + f.name } ) res1: String = "The fruits on this list are: apple pear cherry st rawberry honeydew" REDUCE scala> theList.fold(0)( { (count: Int, f: Fruit) => count + " " + f.totalPieces } ) res2: Int = 42300 theList.reduce( { (f: Fruit) => f.totalPieces } ) res3: Int = 42300
  • 42. NESTED FOR-LOOPS def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]): List(Serving[Pie, IceCream]) { val servings = List[Serving[Pie,IceCream]]() for (p <- 0 until pies.length) { for (i <- 0 until iceCreams.length) { val serving = new Serving(p, i) serving :: servings } } servings } def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]): List(Serving[Pie, IceCream]) { pies.map( { (p: Pie) => iceCreams.map( { (i: IceCream) => new Serving(p, i) } ) } ) }
  • 43. IS THIS AN IMPROVEMENT? def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]): L ist(Serving[Pie, IceCream]) { val servingsLists = pies.map( { (p: Pie) => iceCreams.map( { (i: IceCream) => new Serving(p, i) } ) } ) servingsLists.flatten }
  • 44. FUNCTION COMPOSITION def bakeAPie(f: Fruit, c: Crust): Pie def eatAPie(p: Pie): HappyKelsey def bakeAndEatAPie(f: Fruit, c: Crust): HappyKelsey = eatAPie com pose bakeAPie //could also be written bakeAPie andThen eatAPie flatten compose map is flatMap, and it's MAGIC
  • 45. FOR-YIELD def tryAllPairings(pies: List[Pie], iceCreams: List[IceCream]): List(Serving[Pie, IceCream]) { for { p <- pies i <- iceCreams } yield { new Serving(p,i) } } beautiful!
  • 46. FUN WITH FOR-YIELD def goodPairings(pies: List[Pie], iceCreams: List[IceCream]): Li st(Serving[Pie, IceCream]) { for { p <- pies i <- iceCreams val serving = new Serving(p,i) if (serving.isGood) } yield { serving } } def pleaseEverybody(audience: List[Person], pies: List[Pie], ice Creams: List[IceCream]): List(ThankYou) { for { person <- audience p <- pies i <- iceCreams val serving = new Serving(p,i) if (serving.isGood) } yield { person.feed(serving) } }
  • 47. partial application higher order functions function composition for-yield
  • 48. AND NOW FOR SOMETHING (NOT REALLY) COMPLETELY DIFFERENT
  • 49. NULL.
  • 50. YUCK public Serving<Pie, IceCream> serveBestALaMode(Pie key, Map<Pie, IceCream> pairings) { if(pairings != null) { IceCream iceCream = pairings.get(key); if(iceCream != null) { return new Serving(key, iceCream) } else { return null; } } } SCALA PROGRAMMING DOESN'T USE NULL. YIPPEE!
  • 51. OPTION Option[T] is either a Some with a value of type T inside, or None representing nothing. val someOption: Option[String] = Some("this is a value") val noneOption: Option[String] = None val theSomeValue = someOption.get //returns "this is a value" val someIsDefined = someOption.isDefined //returns true val theNoneValue = noneOption.get //throws NoSuchElementException val someIsDefined = someOption.isDefined //returns false
  • 52. def serveBestALaMode(key: Pie, pairings: Map[Pie, IceCream]): Op tion[Serving[Pie,IceCream]] = { iceCream: Option[IceCream] = pairings.get(key); if (iceCream.isDefined) { Some(new Serving(key, iceCream.get)) } else { None } }
  • 53. OPTION IS KIND OF LIKE A COLLECTION .MAP someOption.map( {(str:String) => str + " SAN DIMAS HIGH SCHOOL FO OTBALL RULES"} ) //returns Some("this is a value SAN DIMAS HIGH SCHOOL FOO TBALL RULES") noneOption.map( {(str:String) => str + " SAN DIMAS HIGH SCHOOL FO OTBALL RULES"} ) //returns None .FLATMAP val favoritePie: Option[Pie] = Some(rhubarb) favoritePie.map({ (pie: Pie) => pairings.get(pie) }) //returns Some(Some(butterPecan))--whoops! favoritePie.flatMap( { (pie: Pie) => pairings.get(pie) } ) //returns Some(butterPecan) .FILTER val todaysSpecial: Option[Pie] val myOrder = todaysSpecial.filter( { (pie: Pie) => (pie != butte rPecan) }
  • 54. FOR-YIELD OVER OPTION for { pie <- todaysSpecial bestIceCream <- pairings.get(pie) iceCream <- availableFlavors.get(bestIceCream) } yield { myDessert } beautiful powerful tough to mess with
  • 55. OPTION IS A MONAD WHAT IS A MONAD?
  • 56. "Let’s look at what it is that makes Thing a monad. The first thing is that I can wrap up a value inside of a new Thing...We have a function of type A => Thing; a function which takes some value and wraps it up inside a new Thing. We also have this fancy bind function, which digs inside our Thing and allows a function which we supply to use that value to create a new Thing. Scala calls this function “flatMap“.... What’s interesting here is the fact that bind is how you combine two things together in sequence. We start with one thing and use its value to compute a new thing." —Daniel Spiewak
  • 57. FLATMAP IS MAGIC flatMap hides our boilerplate. For Lists, it abstracts away a for-loop, letting us create a new List from an existing list. For Options, it abstracts away a null check, letting us create a new nullable value from an existing one. tough to mess with
  • 58. OTHER MONADS accumulating errors a cursor position in a database or file states in a state machine an environment that changes powerful
  • 59. EXTRA CREDIT WHOA A SEMICOLON IS A MONAD
  • 60. partial application higher order functions function composition for-yield monads
  • 62. READABILITY “Is Clojure code hard to understand? Imagine if every time you read Java source code and encountered syntax elements like if statements, for loops, and anonymous classes, you had to pause and puzzle over what they mean. There are certain things that must be obvious to a person who wants to be a productive Java developer. Likewise there are parts of Clojure syntax that must be obvious for one to efficiently read and understand code. Examples include being comfortable with the use of let, apply, map, filter, reduce and anonymous functions...”—R. Mark Volkmann
  • 63. DSLS class HelloWorldSpec extends Specification { "The 'Hello world' string" should { "contain 11 characters" in { "Hello world" must have size(11) } "start with 'Hello'" in { "Hello world" must startWith("Hello") } "end with 'world'" in { "Hello world" must endWith("world") } } } from specs2
  • 64. PURITY “The truth is that good programmers mix the styles quite a bit. We program imperatively when needed, and functionally when possible.” - Michael O. Church