Skip to content

damianfral/slides-functional-programming-coffeescript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Intro to Functional Programming with CoffeeScript

Damián Franco Álvarez

Programming Paradigms

  • What is a paradigm? Style, concepts, models, patterns...
  • Imperative programming
    • Structured programming (C)
      • Problem: goto -> Solution: subroutines and loops
    • Object oriented programming (Java)
      • Problem: global state -> Solution: encapsulation (classes, objects)
  • Declarative
    • Functional programming (Haskell)
      • Problem: state -> Solution: functions (morphism)

Some notes

  • Open your mind
  • Forget imperative programming
  • The click moment

Pure functions

  • The output of a pure function only depends on its inputs
  • Pure funcions does not have side effects
  • Easier to design
  • Easier to read/understand
  • Easy to test
  • FP emphasize on writing pure, generic functions which could work in any environment, and choosing actual program behaviour at the top of the call hierarchy

Currying

  • Transforming a function that receives multiple arguments into a function that receives only one argument:

    # ((a, b) -> c) -> a -> b -> c
    curry = (f) ->
            (a) ->
                    (b) ->
                            f(a,b)
    
    _add = (x,y) -> x + y
    add  = curry _add
    add(2)(3) # ==> 5
    add7 = add 7
    add7 10  # ==> 17
    

Higher order functions

  • Functions that operate on other functions
    • Takes one or more functions as input
    • Outputs a function
  • Well known examples: map, filter, reduce...
  • HOFs facilitates composability and code reusability

Higher order functions

  • Writting pure higher order curried functions in CoffeeScript is easy and powefull:

    map = (f) ->
            (list) ->
                    return (f x for x in list)
    
    map(add7)([1, 2, 3]) # ==> [ 9, 10, 12 ]
    

Higher order functions

filter = (f) ->
        (list) ->
                result = []
                for x in list
                        result.push x if f x
                return result

odd = (num) -> num % 2

filter(odd)([1..10]) # ==> [ 1, 3, 5, 7, 9 ]

Higher order functions

fold = (f) ->
        (init) ->
                acc = init
                (list) ->
                        acc = f(acc)(x) for x in list
                        return acc

sum = fold(add)(0)

sum [1..43] # ==> 946

mult    = (x) -> (y) -> x * y
product = fold(mult)(1)

factorial = (x) -> product [1...x]
factorial 6 # => 120

Function composition

f :  B --> C
g :  A --> B

f . g :  A --> C
negate = (bool) -> ! bool

odd = (num) -> num % 2

even = compose(negate)(odd)

Function composition

comp = (f) ->
        (g) ->
                (args...) ->
                        return f(g.apply @, args)

head = (list) -> list[0]
tail = (list) -> list[1..]

fold1 = (fn) ->
        (list) ->
                fold(fn)(head list)(tail list)

compose = fold1(comp)

# Naive example
bestStudent = compose [head, (sortBy meanQualification), (filter hasPassedAllExames)]

Example

  • Get the most common element in a list
mostCommon [1,7,200,6,3,7,7,999,1,44] # ==> 7
mostCommon 'functional programming!'  # ==> 'n'

Example

compare = (x) ->
        (y) ->
                return  1 if x > y
                return -1 if x < y
                return  0

equal  = (x) -> (y) -> x is y

negate = (bool) -> ! bool

maxBy = (fn) ->
        (x) ->
                (y) ->
                        return y if fn(x)(y) is -1
                        return x

maximumBy = (fn) ->
                fold1(maxBy(fn))

Example

reject = (fn) ->
        return filter(compose [negate, fn])

split = (fn) ->
        (list) ->
                fullfilled  = filter(fn)(list)
                rejected    = reject(fn)(list)
                return [fullfilled, rejected]

Example

groupBy = (fn) ->
        (list) ->
                return [] unless list.length
                x        = head list
                xs       = tail list
                [ys, zs] = split(fn x)(xs)
                # Recursion
                return [[x].concat(ys)].concat(groupBy(fn)(zs))

group = groupBy equal

group [6,7,8,6,7,8,9,1] # [ [ 6, 6 ], [ 7, 7 ], [ 8, 8 ], [ 9 ], [ 1 ] ]

Example

length        = (list)  -> list.length
compareLength = (list1) ->
        (list2) ->
                compare(length list1)(length list2)

mostCommon = compose [head, (maximumBy compareLength), group]

mostCommon [1,7,200,6,3,7,7,999,1,44] # ==>  7
mostCommon 'functional programming'   # ==> 'n'

Why functional programming?

  • Higher abstraction level
  • Reusability
  • Concision
  • Readability

Deeping into FP

  • Algebraic data structures
  • Cathegory theory
  • Typeclasses
  • Laziness
  • Recursion

About

Slides about higher-order programming in CoffeeScript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages