Slide 1

Slide 1 text

A (not so) gentle introduction to functional programming ! @gcapizzi

Slide 2

Slide 2 text

I. Let’s get started

Slide 3

Slide 3 text

What is FP? Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids side effects and mutable data.

Slide 4

Slide 4 text

What is FP? • A function doesn’t do anything • It’s just a mapping between a domain and a codomain • Input and output values already exist

Slide 5

Slide 5 text

What is FP? … -1 0 1 2 3 … … 0 1 2 3 4 … domain codomain f(x) = x + 1

Slide 6

Slide 6 text

Values vs identities • A value is something that doesn't change • An identity is a stable logical entity associated with a series of different values over time • A state is the value of an identity at a point in time

Slide 7

Slide 7 text

Values vs identities • Objects are identities • So are real world objects, or at least that’s how we perceive them • Typical OOP has imperative programming baked into it

Slide 8

Slide 8 text

“No man ever steps in the same river twice, for it's not the same river and he's not the same man.” — Heraclitus

Slide 9

Slide 9 text

“Identities are mental tools we use to superimpose continuity on a world which is constantly, functionally, creating new values of itself.” — Rich Hickey

Slide 10

Slide 10 text

“Equality in the presence of mutability has no meaning.” ! — Michael Fogus

Slide 11

Slide 11 text

Why FP? Functions are easier to • understand • reason about • refactor • test

Slide 12

Slide 12 text

Why FP? Functions can be • evaluated lazily • cached / memoized • massively parallelized

Slide 13

Slide 13 text

“Immutable objects are always thread safe.” ! — Brian Goetz

Slide 14

Slide 14 text

Throw away your loops! ! sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + sum xs Example 1

Slide 15

Slide 15 text

II. Function as things

Slide 16

Slide 16 text

FP • Functions • Functions • Functions, also • Functions • Yes, functions • Oh my, functions again! • Functions • Functions :) OOP • Single Responsibility Principle • Open/Closed principle • Dependency Inversion Principle • Interface Segregation Principle • Factory pattern • Strategy pattern • Decorator pattern • Visitor pattern From OOP to FP

Slide 17

Slide 17 text

From OOP to FP

Slide 18

Slide 18 text

Functions are values! Let’s take SRP and ISP to the extreme: ! interface BunchOfStuff { int doSomething(int x); string doSomethingElse(int x); void doAThirdThing(string x); }

Slide 19

Slide 19 text

Functions are values! Let’s take SRP and ISP to the extreme: ! interface IntToIntFunction { int invoke(int x); }

Slide 20

Slide 20 text

“Verbs in Javaland are responsible for all the work, but as they are held in contempt by all, no Verb is ever permitted to wander about freely. If a Verb is to be seen in public at all, it must be escorted at all times by a Noun.” ! — Steve Yegge

Slide 21

Slide 21 text

Functions are values! That interface is equivalent to the following type: ! Int -> Int which is the type of every function taking an integer and returning an integer.

Slide 22

Slide 22 text

interface Action { Response call(Request request); } ! interface EmailValidator { boolean validateEmail(String email); } Example 2

Slide 23

Slide 23 text

class UpdateProfile implements Action { private EmailValidator emailValidator; ! public UpdateProfile(EmailValidator emailValidator) { this.emailValidator = emailValidator; } ! public Response call(Request request) { … } } Example 2

Slide 24

Slide 24 text

isValidEmail :: String -> Bool isValidEmail = … ! updateProfile :: (String -> Bool) -> Request -> Response updateProfile emailValidation req resp = … ! —— Partial application as Dependency Injection ! updateProfileIfEmailIsValid :: Request -> Response updateProfileIfEmailIsValid = updateProfile isValidEmail ! —— *Any* function of type (String -> Bool) will do! ! updateProfileIfEmailIsPalindrome = updateProfile isPalindrome Example 2

Slide 25

Slide 25 text

f :: Int -> Int -> Int -> Int f x y z = … —— or f x y = \z -> … —— or f x = \y -> \z -> … —— or f = \x -> \y -> \z -> … Currying

Slide 26

Slide 26 text

sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + sum xs ! prod :: [Int] -> Int prod [] = 1 prod (x:xs) = x * prod xs High-order functions

Slide 27

Slide 27 text

foldl :: (b -> a -> b) -> b -> [a] -> b foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs ! sum :: [Int] -> Int sum = foldl (+) 0 ! prod :: [Int] -> Int prod = foldl (*) 1 High-order functions

Slide 28

Slide 28 text

map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs ! strToUpper :: String -> String strToUpper = map toUpper ! doubleAll :: [Int] -> [Int] doubleAll = map (*2) High-order functions

Slide 29

Slide 29 text

filter :: (a -> Bool) -> [a] -> [a] filter f [] = [] filter f (x:xs) | f x = x : filter f xs | otherwise = filter f xs ! ! filterEven = filter (\x -> x `mod` 2 == 0) filterAlpha = filter isAlpha High-order functions

Slide 30

Slide 30 text

III. Composition

Slide 31

Slide 31 text

(g ∘ f )(x) = g(f(x))

Slide 32

Slide 32 text

splitDelim :: String -> String -> [String] splitDelim delim = splitRegex (mkRegex delim) ! stringsToInts :: [String] -> [Int] stringsToInts = map read ! sumString :: String -> Int sumString = sum . stringsToInts . splitDelim “,” ! > sumString “1,2,3,4,5” —— 15 Example 3

Slide 33

Slide 33 text

extractUserAgent :: String -> String extractUserAgent = … ! countUserAgents :: String -> Int countUserAgents = length . nub . map extractUserAgent . filter (not . null) . lines Example 4

Slide 34

Slide 34 text

IV. Functions all the way down

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Request updateProfile Response

Slide 37

Slide 37 text

Request fromReq Customer saveCustomer Customer toResponse Response

Slide 38

Slide 38 text

Request fromReq Customer validate Valid Customer update Valid Customer toResponse Response

Slide 39

Slide 39 text

V. Questions?