Slide 1

Slide 1 text

The State of Functional Programming

Slide 2

Slide 2 text

• Leif Gensert • Web Developer •Trying to get better at FP

Slide 3

Slide 3 text

• Code in Ruby and Elixir • Small amount of stdlib • Not all code is runnable

Slide 4

Slide 4 text

What is Functional Programming? fraction1 = Fraction.new(1, 2) # 1/2 fraction2 = Fraction.new(3, 4) # 3/4 new_fraction = fraction1.add(fraction2) new_fraction # 5/4 OR fraction1.add(fraction2) fraction1 # 5/4 fraction1 = Fraction.new(1, 2) # 1/2 fraction2 = Fraction.new(3, 4) # 3/4 new_fraction = add(fraction1, fraction2) new_fraction # 5/4 OR?

Slide 5

Slide 5 text

fraction = Fraction.new(1, 2) fraction # 2/3 magic_function(fraction, 2, 3) fraction = Fraction.new(2, 3) fraction.numerator = 2 fraction.denominator = 3 fraction.set_numerator(2) fraction.set_denominator(3)

Slide 6

Slide 6 text

Functional Programming Immutable Data Structures

Slide 7

Slide 7 text

fraction = Fraction.new(1, 2) do_something(fraction) fraction Downside of Mutable Data Structures

Slide 8

Slide 8 text

Immutable Other Mutable

Slide 9

Slide 9 text

fav_albums1 = [ ] fav_albums2 = List.delete_at(fav_albums1, 0) fav_albums2 = [ ]

Slide 10

Slide 10 text

fav_albums1 fav_albums2 * Persistent Data Structures

Slide 11

Slide 11 text

Challenge

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Artist Album Green Day Dookie Green Day American Idiot Britney Spears … Baby One More Time Britney Spears In The Zone Britney Spears Circus { "Green Day" => [ "Dookie", "American Idiot" ], "Britney Spears" => [ "... Baby One More Time", "In The Zone", "Circus" ], }

Slide 14

Slide 14 text

{ "Green Day" => [ "Dookie", "American Idiot" ], "Britney Spears" => [ "... Baby One More Time", "In The Zone", "Circus" ], } [ ["Green Day", "Dookie"], ["Green Day", "American Idiot"], ["Britney Spears", "... Baby One More Time"], ["Britney Spears", "In The Zone"], ["Britney Spears", "Circus"], ]

Slide 15

Slide 15 text

1 def make_map(albums_list) 2 albums_map = {} 3 4 for i in (0..albums_list.length - 1) do 5 artist, album = albums_list[i] 6
 7 cur_albums = albums_map[artist] 8 if cur_albums 9 cur_albums << album 10 albums_map[artist] = cur_albums 11 else 12 albums_map[artist] = [album] 13 end 14 end 15 16 albums_map 17 end

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

1 def make_map(albums_list, map) do 2 if album_list == [] do 3 map 4 else 5 [ head | rest] = albums_list 6 7 [artist, album] = head 8 9 cur_albums = Map.get(map, artist) 10 11 if cur_albums do 12 new_albums = [ album | cur_albums ] 13 new_map = Map.put(map, artist, new_albums) 14 make_map(rest, new_map) 15 else 16 new_map = Map.put(map, artist, [album]) 17 make_map(rest, new_map) 18 end 19 end 20 end

Slide 18

Slide 18 text

1 def make_map(albums_list, map) do 2 if album_list == [] do 3 map 4 else 5 [ head | rest] = albums_list 6 7 [artist, album] = head 8 9 cur_albums = Map.get(map, artist) 10 11 if cur_albums do 12 new_albums = [ album | cur_albums ] 13 new_map = Map.put(map, artist, new_albums) 14 make_map(rest, new_map) 15 else 16 new_map = Map.put(map, artist, [album]) 17 make_map(rest, new_map) 18 end 19 end 20 end

Slide 19

Slide 19 text

map filter reduce

Slide 20

Slide 20 text

filter &britney? 13 11 13 map &num_of_tracks 37 reduce &sum_each(0)

Slide 21

Slide 21 text

The Big Picture

Slide 22

Slide 22 text

Global State

Slide 23

Slide 23 text

class Database @store = {} def self.get(key) @store[key] end def self.insert(key, value) @store[key] = value end def self.drop @store = {} end end Database.insert("Green Day", ["Dookie"]) Database.get("Green Day") # ["Dookie"]

Slide 24

Slide 24 text

Message Passing

Slide 25

Slide 25 text

else if message == {"insert", key, value} do Map.put(store, key, value) send(from, "ok") end *Pseudocode def run(store) do receive from, message do end end reference = spawn run(%{"Green Day" => ["Dookie"]}) send(reference, {"get", "Green Day"}) # ["Dookie"] if message == {"get", key} do send(from, Map.get(store, key))

Slide 26

Slide 26 text

def run(store) do receive from, message do if message == {"get", key} do send(from, Map.get(store, key)) else if message == {"insert", key, value} do new_store = Map.put(store, key, value) send(from, "ok") end end end reference = spawn run(%{}) send(reference, {"insert", "Green Day", ["Dookie"]}) send(reference, {"get", "Green Day", ["Dookie"]}) # ["Dookie"] run(new_store) run(store)

Slide 27

Slide 27 text

Elixir.Agent

Slide 28

Slide 28 text

{:ok, reference} = Agent.start_link(fn -> %{} end) Agent.update( reference, fn store -> Map.put(store, "Green Day", ["Dookie"]) end ) Agent.get( reference, fn store -> Map.get(store, "Green Day") end )

Slide 29

Slide 29 text

Agent.start_link(fn -> %{} end, name: :albums) Agent.update( :albums, fn store -> Map.put(store, "Green Day", ["Dookie"]) end ) Agent.get( :albums, fn store -> Map.get(store, "Green Day") end )

Slide 30

Slide 30 text

• Functional Programming Immutability • Get used to recursion • State can be stored in Functions

Slide 31

Slide 31 text

No content