On Github damianfral / slides-functional-programming-coffeescript
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
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 ]
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 ]
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
f : B --> C g : A --> B f . g : A --> C
negate = (bool) -> ! bool odd = (num) -> num % 2 even = compose(negate)(odd)
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)]
mostCommon [1,7,200,6,3,7,7,999,1,44] # ==> 7 mostCommon 'functional programming!' # ==> 'n'
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))
reject = (fn) -> return filter(compose [negate, fn]) split = (fn) -> (list) -> fullfilled = filter(fn)(list) rejected = reject(fn)(list) return [fullfilled, rejected]
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 ] ]
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'