Slide 1

Slide 1 text

FUNCTIONAL PROGRAMMING IN JAVASCRIPT A SIMPLE INTRO Created by Grégoire Charvet

Slide 2

Slide 2 text

WHAT IS FP? There is no unique definition. More a group of programming patterns. Functional languages: Haskell ML OCaml The lisp family (common Lisp and Closure) Scala (mixed OO & Functional) Erlang

Slide 3

Slide 3 text

OOP VS FP OOP focus on difference between data FP focus on consistent data structures

Slide 4

Slide 4 text

OOP Data tightly coupled with logic Core concept: encapsulation Code reuse achieved with inheritance and composition Abstraction model is the data itself FP Data is loosely coupled with logic Core concept: function composition Code reuse achived with function composition and higher order function Abstraction model is the function

Slide 5

Slide 5 text

SQL SAMPLE S E L E C T o r d e r s . o r d e r _ i d , o r d e r s . o r d e r _ d a t e , s u p p l i e r s . s u p p l i e r _ n a m e F R O M s u p p l i e r s R I G H T O U T E R J O I N o r d e r s O N s u p p l i e r s . s u p p l i e r _ i d = o r d e r s . s u p p l i e r _ i d W H E R E o r d e r s . o r d e r _ s t a t u s = ' I N C O M P L E T E ' O R D E R B Y o r d e r s . o r d e r _ d a t e D E S C ; Consistent data structure (table with schema) Few functions combined together Declarative language Very close to a functional paradigm

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Utility belts Lots of functional ideas

Slide 8

Slide 8 text

LODASH EXAMPLE _ . m a p ( [ 1 , 3 , 5 ] , a d d 3 ) ; / / [ 4 , 6 , 8 ] More about map later

Slide 9

Slide 9 text

INTRODUCING RAMDA Lodash/underscore FP alternative Not a drop-in replacement. It's a different approach to programming

Slide 10

Slide 10 text

_ . m a p ( [ 1 , 3 , 5 ] , a d d 3 ) ; / / [ 4 , 6 , 8 ] R . m a p ( a d d 3 , [ 1 , 3 , 5 ] ) ; / / [ 4 , 6 , 8 ] Order of arguments is reversed. Collection is at the end.

Slide 11

Slide 11 text

ONE STEP BACK Add 5? Add arbitrary constant? Only known at runtime?

Slide 12

Slide 12 text

OOP STYLE f u n c t i o n A d d e r ( c o n s t a n t ) { t h i s . c o n s t a n t = c o n s t a n t ; } A d d e r . p r o t o t y p e . g e t A d d F u n c t i o n ( ) { v a r c o n s t a n t = t h i s . f u n c t i o n ( ) ; r e t u r n f u n c t i o n ( n u m ) { r e t u r n n u m + c o n s t a n t ; } ; } v a r a d d 5 = n e w A d d e r ( 5 ) ; _ . m a p ( a d d e r . g e t A d d F u n c t i o n ( ) , [ 1 , 3 , 5 ] ) ;

Slide 13

Slide 13 text

IMPERATIVE STYLE _ . m a p ( f u n c t i o n ( n u m ) { r e t u r n n u m + 5 ; } , [ 1 , 3 , 5 ] ) ;

Slide 14

Slide 14 text

FP STYLE Define a generic function to add two numbers f u n c t i o n a d d ( a , b ) { r e t u r n a + b ; } and curry it a d d = R . c u r r y ( a d d ) ; v a r a d d 5 = a d d ( 5 ) ; R . m a p ( a d d 5 , [ 1 , 3 , 5 ] ) ;

Slide 15

Slide 15 text

translate into: CURRYING ALSO KNOWN AS PARTIAL APPLICATION v a r a d d 5 = a d d ( 5 ) ; v a r a d d 5 = f u n c t i o n ( a ) { r e t u r n a d d ( 5 , a ) ; } a d d ( 5 , 3 ) = = = a d d ( 5 ) ( 3 ) ;

Slide 16

Slide 16 text

All Ramda methods are automatically curried. R . m a p ( a d d 3 , [ 1 , 3 , 5 ] ; R . m a p ( a d d 3 ) ( [ 1 , 3 , 5 ] ) ; Collection as the last argument makes sense with currying

Slide 17

Slide 17 text

MORE COMPLEX EXAMPLE Goal: list all languages used by a given github user in 2014 or 2015

Slide 18

Slide 18 text

GET ALL REPOS FOR A USER G E T h t t p s : / / a p i . g i t h u b . c o m / u s e r s / : u s e r / r e p o s [ { " i d " : 1 2 3 1 7 2 0 4 , " n a m e " : " a b i d e " , " f u l l _ n a m e " : " h i d d e n t a o / a b i d e " , " o w n e r " : { . . . } , " u p d a t e d _ a t " : " 2 0 1 4 - 0 4 - 2 7 T 0 8 : 5 9 : 1 8 Z " , " p r i v a t e " : f a l s e , " h t m l _ u r l " : " h t t p s : / / g i t h u b . c o m / h i d d e n t a o / a b i d e " , " d e s c r i p t i o n " : " B a s e c l a s s w i t h p u b - s u b a n d o b s e r v e r s f o r J S o b j " f o r k " : f a l s e , " u r l " : " h t t p s : / / a p i . g i t h u b . c o m / r e p o s / h i d d e n t a o / a b i d e " , " l a n g u a g e s _ u r l " : " h t t p s : / / a p i . g i t h u b . c o m / r e p o s / h i d d e n t a o / a b i d e / l " l a n g u a g e " : " J a v a S c r i p t " , } , { . . . } ]

Slide 19

Slide 19 text

GET LANGUAGES FOR A REPO G E T h t t p s : / / a p i . g i t h u b . c o m / u s e r s / : u s e r / : r e p o n a m e / l a n g u a g e s { " J a v a S c r i p t " : 1 1 1 0 3 , " C o f f e e S c r i p t " : 1 3 9 8 }

Slide 20

Slide 20 text

(more on next slides) SIMPLE IMPERATIVE APPROACH v a r g e t Y e a r L a n g u a g e s = f u n c t i o n ( y e a r / * Y Y Y Y * / ) { r e t u r n f e t c h R e p o s ( ) . t h e n ( f u n c t i o n ( r e p o s ) { v a r y e a r R e p o = [ ] ; f o r ( v a r i = 0 , l e n = r e p o s . l e n g t h ; i < l e n ; + + i ) { i f ( r e p o s [ i ] . u p d a t e d _ a t . s l i c e ( 0 , 4 ) > = y e a r ) { y e a r R e p o . p u s h ( r e p o s [ i ] ) ; } } ; r e t u r n y e a r R e p o s ; } )

Slide 21

Slide 21 text

(even more on next slides) . t h e n ( f u n c t i o n ( r e p o s ) { v a r l a n g u a g e s P = [ ] ; f o r ( v a r i = 0 , l e n = r e p o s . l e n g t h ; i < l e n ; + + i ) { i f ( r e p o s [ i ] . l a n g u a g e s ) { l a n g u a g e s P . p u s h ( g e t R e p o L a n g u a g e s ( r e p o . l a n g u a g e s _ u r l ) ) ; } } r e t u r n l a n g u a g e s P ; } ) . t h e n ( P r o m i s e . a l l )

Slide 22

Slide 22 text

(even more on next slides) . t h e n ( f u n c t i o n ( l a n g u a g e s ) { v a r r e s u l t = { } ; f o r ( v a r i = 0 , l e n = l a n g u a g e s . l e n g t h ; i < l e n ; + + i ) { f o r ( v a r l a n g i n l a n g u a g e s [ i ] ) { i f ( ! r e s u l t [ l a n g ] ) r e s u l t [ l a n g ] = 0 ; r e s u l t [ l a n g ] + = l a n g u a g e s [ i ] [ l a n g ] ; } } ; r e t u r n r e s u l t ; } )

Slide 23

Slide 23 text

. t h e n ( f u n c t i o n ( s u m m a r y ) { v a r a r r = [ ] ; f o r ( v a r l a n g u a g e i n s u m m a r y ) { a r r . p u s h ( { l a n g u a g e : l a n g u a g e , c o u n t : s u m m a r y [ l a n g u a g e ] } ) ; } r e t u r n a r r ; } ) . t h e n ( f u n c t i o n ( s u m m a r y ) { / / m o s t u s e d l a n g u a g e f i r s t r e t u r n s u m m a r y . s o r t ( f u n c t i o n ( l a , l b ) { r e t u r n l a . c o u n t > l b . c o u n t ? 1 : l a . c o u n t < l b . c o u n t ? - 1 : 0 ; } ) ; } ) ; } / / e n d o f t h e f u n c t i o n g e t Y e a r L a n g u a g e s

Slide 24

Slide 24 text

SIMILAR OOP METHOD v a r g e t Y e a r L a n g u a g e s = f u n c t i o n ( y e a r / * Y Y Y Y * / ) { r e t u r n f e t c h R e p o s ( ) . t h e n ( f u n c t i o n ( r e p o s ) { v a r r e p o L i s t = n e w R e p o L i s t ( r e p o s ) ; r e p o L i s t . c h o o s e B y Y e a r ( y e a r ) ; r e t u r n r e p o L i s t . g e t L a n g u a g e s ( ) ; } ) . t h e n ( f u n c t i o n ( l a n g u a g e s ) { v a r l a n g u a g e L i s t = n e w L a n g u a g e L i s t ( l a n g u a g e s ) ; v a r s o r t e r = n e w L a n g u a g e S o r t e r ( ' c o u n t ' ) ; l a n g u a g e L i s t . s o r t ( s o r t e r . g e t S o r t F u n c t i o n ( ) ) ; r e t u r n l a n g u a g e L i s t . l a n g u a g e s ; } ) ; }

Slide 25

Slide 25 text

f u n c t i o n R e p o L i s t ( r e p o s / * R e p o s [ ] * / ) { t h i s . r e p o s = r e p o s ; } R e p o L i s t . p r o t o t y p e . c h o o s e B y Y e a r = f u n c t i o n ( y e a r / * Y Y Y Y * / ) { v a r r e s u l t s = [ ] ; f o r ( v a r i = 0 , l e n = t h i s . r e p o s . l e n g t h ; i > l e n ; + + i ) { i f ( t h i s . r e p o s [ i ] . u p d a t e d _ a t . s l i c e ( 0 , 4 ) > = y e a r ) { r e s u l t s . p u s h ( t h i s . r e p o s [ i ] ) ; } } t h i s . r e p o s = r e s u l t s ; }

Slide 26

Slide 26 text

R e p o L i s t . p r o t o t y p e . g e t L a n g u a g e s = f u n c t i o n ( ) { v a r l a n g u a g e s P = [ ] ; f o r ( v a r i = 0 , l e n = t h i s . r e p o s . l e n g t h ; i > l e n ; + + i ) { i f ( t h i s . r e p o s [ i ] . l a n g u a g e ) { l a n g u a g e s P . p u s h ( t h i s . r e p o s [ i ] . l a n g u a g e s _ u r l ) ; } } r e t u r n P r o m i s e . a l l ( l a n g u a g e s P ) ; }

Slide 27

Slide 27 text

f u n c t i o n L a n g u a g e L i s t ( l a n g u a g e s ) { t h i s . l a n g u a g e s = [ ] ; v a r s u m m a r y = { } ; f o r ( v a r i = 0 , l e n = l a n g u a g e s . l e n g t h ; i > l e n ; + + i ) { f o r ( v a r l a n g i n l a n g u a g e s ) { i f ( ! s u m m a r y [ l a n g ] ) s u m m a r y [ l a n g ] = { l a n g u a g e : l a n g , c o u n t : 0 } ; s u m m a r y [ l a n g ] . c o u n t + = l a n g u a g e s [ i ] [ l a n g ] ; } } f o r ( v a r s i n s u m m a r y ) { t h i s . l a n g u a g e s . p u s h ( s ) ; } } L a n g u a g e L i s t . p r o t o t y p e . s o r t = f u n c t i o n ( s o r t e r / * l a n g u a g e S o r t e r * / ) { t h i s . l a n g u a g e s . s o r t ( s o r t e r ) ; }

Slide 28

Slide 28 text

f u n c t i o n L a n g u a g e S o r t e r ( p r o p ) { t h i s . p r o p = p r o p } L a n g u a g e S o r t e r . p r o t o t y p e . g e t S o r t F u n c t i o n = f u n c t i o n ( ) { r e t u r n f u n c t i o n ( a , b ) { r e t u r n a [ t h i s . p r o p ] > b [ t h i s . p r o p ] ? 1 : a [ t h i s . p r o p ] < b [ t h i s . p r o p ] ? - 1 : 0 ; } }

Slide 29

Slide 29 text

The content of the methods are roughly similar. t h i s is only used for organization. So let's focus on the imperative code (a bit simpler)

Slide 30

Slide 30 text

FP WITH RAMDA Conversion guide

Slide 31

Slide 31 text

. t h e n ( f u n c t i o n ( r e p o s ) { v a r y e a r R e p o = [ ] ; f o r ( v a r i = 0 , l e n = r e p o s . l e n g t h ; i < l e n ; + + i ) { i f ( r e p o s [ i ] . u p d a t e d _ a t . s l i c e ( 0 , 4 ) > = y e a r ) { y e a r R e p o . p u s h ( r e p o s [ i ] ) ; } } ; r e t u r n y e a r R e p o s ; } FILTER!

Slide 32

Slide 32 text

ACTION PLAN extract the attribute `updated_at` extract the year in this attribute filter by comparing with given year

Slide 33

Slide 33 text

EXTRACTION R . p r o p ( ' u p d a t e d _ a t ' ) ; So, what's the R.prop function is?

Slide 34

Slide 34 text

In Ramda it is: GET DEFINITION R . p r o p = c u r r y ( f u n c t i o n ( p r o p , o b j ) { r e t u r n o b j [ p r o p ] ; } ) ; Without the curry wrapper prop is only the accessor function R . p r o p ( ' u p d a t e d _ a t ' ) ; / / r e t u r n s a f u n c t i o n t a k i n g o n e o b j e c t a r g u m e n t R . p r o p ( ' u p d a t e d _ a t ' ) ( o b j ) ; / / r e t u r n s o b j . u p d a t e d _ a t

Slide 35

Slide 35 text

GET THE YEAR R . s l i c e ( 0 , 4 ) again: Ramda function are automatically curried.

Slide 36

Slide 36 text

FILTERING IN ES5 A r r a y . p r o t o t y p e . f i l t e r ( p r e d i c a t e ) ; With ramda R . f i l t e r ( p r e d i c a t e , c o l l e c t i o n ) ; We need a predicate: function which returns a boolean Predicate: true iff obj.updated_at begins with 2015 or 2014.

Slide 37

Slide 37 text

PUTTING IT TOGETHER WITH COMPOSE The similar equivalent in lodash/underscore is chain

Slide 38

Slide 38 text

composing f and g is: R . c o m p o s e ( f , g ) ; / / s a m e a s f u n c t i o n c o m p o s e d ( f , g ) { r e t u r n f u n c t i o n ( x ) { r e t u r n f ( g ( x ) ) ; } } Right associative (read from the right)

Slide 39

Slide 39 text

PREDICATE FUNCTION v a r p r e d i c a t e = R . c o m p o s e ( R . g t e ( y e a r ) , R . s l i c e ( 0 , 4 ) , R . g e t ( ' u p d a t e d _ a t ' ) ) ;

Slide 40

Slide 40 text

REPOS UPDATED AFTER 2014 / / i m p e r a t i v e . t h e n ( f u n c t i o n ( r e p o s ) { v a r y e a r R e p o = [ ] ; f o r ( v a r i = 0 , l e n = r e p o s . l e n g t h ; i < l e n ; + + i ) { i f ( r e p o s [ i ] . u p d a t e d _ a t . s l i c e ( 0 , 4 ) > = y e a r ) { y e a r R e p o . p u s h ( r e p o s [ i ] ) ; } } ; r e t u r n y e a r R e p o s ; } / / f u n c t i o n a l . t h e n ( R . f i l t e r ( R . c o m p o s e ( R . g t e ( y e a r ) , R . s l i c e ( 0 , 4 ) , R . g e t ( ' u p d a t e d _ a t ' ) ) ) ) Even without ramda, you can use [].filter

Slide 41

Slide 41 text

NEXT STEP: GET LANGUAGES . t h e n ( f u n c t i o n ( r e p o s ) { v a r l a n g u a g e s P = [ ] ; f o r ( v a r i = 0 , l e n = r e p o s . l e n g t h ; i < l e n ; + + i ) { i f ( r e p o s [ i ] . l a n g u a g e s ) { l a n g u a g e s P . p u s h ( g e t R e p o L a n g u a g e s ( r e p o . l a n g u a g e s _ u r l ) ) ; } } r e t u r n l a n g u a g e s P ; } )

Slide 42

Slide 42 text

MAP The bread of functional programming The butter is filter

Slide 43

Slide 43 text

MAP Apply a function over every element of a collection to create a new collection of transformed elements. R . m a p ( f u n c t i o n ( a ) { r e t u r n a + 3 } , [ 1 , 3 , 5 ] ) ; / / [ 4 , 6 , 8 ] R . m a p ( f u n c t i o n ( ) { r e t u r n ' f o o ' } , [ 1 , 3 , 5 ] ) ; / / [ ' f o o ' , ' f o o ' , ' f o o ' ] R . m a p ( f u n c t i o n ( a ) { r e t u r n a * a } , [ 1 , 3 , 5 ] ) ; / / [ 1 , 9 , 2 5 ] R . m a p ( p a r s e I n t , [ ' 1 0 ' , ' 1 0 ' , ' 1 0 ' ] ) ; / / [ 1 0 , 1 0 , 1 0 ] _ . m a p ( [ ' 1 0 ' , ' 1 0 ' , ' 1 0 ' ] , p a r s e I n t ) ; / / [ 1 0 , N a N , 2 ] < - c l a s s i c j s w t f Present in ES5: Array.prototype.map(mapper)

Slide 44

Slide 44 text

GET LANGUAGES PER REPO . t h e n ( f u n c t i o n ( r e p o s ) { v a r l a n g u a g e s P = [ ] ; f o r ( v a r i = 0 , l e n = r e p o s . l e n g t h ; i < l e n ; + + i ) { i f ( r e p o s [ i ] . l a n g u a g e s ) { l a n g u a g e s P . p u s h ( g e t R e p o L a n g u a g e s ( r e p o . l a n g u a g e s _ u r l ) ) ; } } r e t u r n l a n g u a g e s P ; } ) . t h e n ( P r o m i s e . a l l ) . t h e n ( R . f i l t e r ( R . g e t ( ' l a n g u a g e s ' ) ) ) . t h e n ( R . m a p ( R . c o m p o s e ( g e t R e p o L a n g u a g e s , R . g e t ( ' l a n g u a g e s _ u r l ' ) ) ) ) . t h e n ( P r o m i s e . a l l )

Slide 45

Slide 45 text

AGGREGATE LANGUAGES STATS . t h e n ( f u n c t i o n ( l a n g u a g e s ) { v a r r e s u l t = { } ; f o r ( v a r i = 0 , l e n = l a n g u a g e s . l e n g t h ; i < l e n ; + + i ) { f o r ( v a r l a n g i n l a n g u a g e s [ i ] ) { i f ( ! r e s u l t [ l a n g ] ) r e s u l t [ l a n g ] = 0 ; r e s u l t [ l a n g ] + = l a n g u a g e s [ i ] [ l a n g ] ; } } ; r e t u r n r e s u l t ; } ) / / i n p u t [ { " j a v a S c r i p t " : 1 2 0 0 } , { " j a v a S c r i p t " : 1 3 3 7 , " s h e l l " : 4 0 } ] / / o u t p u t { " j a v a S c r i p t " : 2 5 3 7 , " s h e l l " : 4 0 }

Slide 46

Slide 46 text

REDUCE Also known as fold in other languages [ ] . r e d u c e ( r e d u c e r , i n i t i a l V a l u e ) ; / / E S 5 r e d u c e r ( a c c u m u l a t o r , c u r r e n t V a l u e )

Slide 47

Slide 47 text

EXAMPLE OF REDUCE get the sum of all element in a collection [ 1 , 3 , 5 ] . r e d u c e ( f u n c t i o n a d d e r ( s u m , n u m ) { r e t u r n s u m + n u m ; } , 0 ) ; f u n c t i o n a d d e r ( 0 , 1 ) - > r e t u r n 0 + 1 f u n c t i o n a d d e r ( 1 , 3 ) - > r e t u r n 1 + 3 f u n c t i o n a d d e r ( 4 , 5 ) - > r e t u r n 4 + 5 f i n a l r e s u l t : 9

Slide 48

Slide 48 text

AGGREGATING LANGUAGES R . r e d u c e ( f u n c t i o n ( a g g r e g a t e d , l a n g u a g e s ) { R . f o r E a c h ( f u n c t i o n ( l a n g ) { i f ( ! a g g r e g a t e d [ l a n g ] ) a g g r e g a t e d [ l a n g ] = 0 ; a g g r e g a t e d [ l a n g ] + = l a n g u a g e s [ l a n g ] ; } ) ( R . k e y s ( l a n g u a g e s ) ) ; r e t u r n a g g r e g a t e d ; } , { } ) ;

Slide 49

Slide 49 text

TRANSFORMING THE AGGREGATED OBJECT INTO AN ARRAY / / i n p u t { " j a v a S c r i p t " : 2 5 3 7 , " s h e l l " : 4 0 } / / o u t p u t [ { " l a n g u a g e " : " j a v a s c r i p t " , " c o u n t " : 2 5 3 7 } , { " l a n g u a g e " : " s h e l l " , " c o u n t " : 4 0 } ]

Slide 50

Slide 50 text

TRANSFORMING THE AGGREGATED OBJECT INTO AN ARRAY R . c o m p o s e ( R . m a p ( f u n c t i o n ( p a i r ) { r e t u r n { l a n g u a g e : p a i r [ 0 ] , c o u n t : p a i r [ 1 ] } } ) , R . t o P a i r s / / { a : 1 , b : 2 } - > [ [ ' a ' , 1 ] , [ ' b ' , 2 ] ] )

Slide 51

Slide 51 text

SORTING LANGUAGES / / i n p u t [ { " l a n g u a g e " : " s h e l l " , " c o u n t " : 4 0 } , { " l a n g u a g e " : " j a v a s c r i p t " , " c o u n t " : 2 5 3 7 } ] / / o u t p u t [ { " l a n g u a g e " : " j a v a s c r i p t " , " c o u n t " : 2 5 3 7 } , { " l a n g u a g e " : " s h e l l " , " c o u n t " : 4 0 } ]

Slide 52

Slide 52 text

SORTING BY COUNT R . s o r t B y ( R . p r o p ( ' c o u n t ' ) ) Sort in increasing order according to a key given by the function R . c o m p o s e ( R . r e v e r s e , R . s o r t B y ( R . p r o p ( ' c o u n t ' ) ) )

Slide 53

Slide 53 text

R.pCompose \o/ RAMDA WITH PROMISES Same as compose, but if something returns a thenable, it'll be handled asynchronously.

Slide 54

Slide 54 text

PUTTING IT ALL TOGETHER v a r g e t L a n g u a g e s = f u n c t i o n ( y e a r / * Y Y Y Y * / ) { r e t u r n R . p C o m p o s e ( s o r t L a n g u a g e s a g g r e g a t e L a n g u a g e s , P r o m i s e . a l l , g e t L a n g u a g e s , c h o o s e B y Y e a r ( y e a r ) , f e t c h R e p o s ) ( ) ; }

Slide 55

Slide 55 text

v a r c h o o s e B y Y e a r = f u n c t i o n ( y e a r ) { r e t u r n R . f i l t e r ( R . c o m p o s e ( R . g t e ( y e a r ) , R . s l i c e ( 0 , 4 ) , R . g e t ( ' u p d a t e d _ a t ' ) ) ) ; }

Slide 56

Slide 56 text

v a r g e t L a n g u a g e s = R . c o m p o s e ( R . m a p ( R . c o m p o s e ( g e t R e p o L a n g u a g e s , R . g e t ( ' l a n g u a g e _ u r l ' ) ) ) , R . f i l t e r ( R . g e t ( ' l a n g u a g e s ' ) ) )

Slide 57

Slide 57 text

v a r a g g r e g a t e L a n g u a g e s = R . r e d u c e ( f u n c t i o n ( a g g r e g a t e d , l a n g u a g e s ) { r e t u r n R . f o r E a c h ( f u n c t i o n ( l a n g ) { i f ( ! a g g r e g a t e d [ l a n g ] ) a g g r e g a t e d [ l a n g ] = 0 ; a g g r e g a t e d [ l a n g ] + = l a n g u a g e s [ l a n g ] ; } ) ( R . k e y s ( l a n g u a g e s ) ) ; } , { } ) ;

Slide 58

Slide 58 text

v a r s o r t L a n g u a g e s = R . c o m p o s e ( R . r e v e r s e , R . s o r t B y ( R . p r o p ( ' c o u n t ' ) ) ) ;

Slide 59

Slide 59 text

WEIRD ORDER? PIPE AND PPIPE Mirror versions of compose and pCompose v a r g e t L a n g u a g e s = f u n c t i o n ( y e a r / * Y Y Y Y * / ) { r e t u r n R . p P i p e ( f e t c h R e p o s , c h o o s e B y Y e a r ( y e a r ) , g e t L a n g u a g e s , P r o m i s e . a l l , a g g r e g a t e L a n g u a g e s , s o r t L a n g u a g e s ) ( ) ; }

Slide 60

Slide 60 text

ESSENCE OF FUNCTIONAL PROGRAMMING Combine (compose) functions with compose & curry Any loop can be expressed with a combination of map, filter, reduce

Slide 61

Slide 61 text

WHAT DO WE GAIN WITH FP? Simplicity Easier decomposition of problems Code more closely tight to problem domain Which leads in turn to: Straightforward unit testing Simple concurrency

Slide 62

Slide 62 text

CAVEATS Big surface API (similar to underscore/lodash actually) Not enough in itself: closures breaks compositions. Avoid states Need immutability FP is weird (at first). Start with map/filter to eliminate for loops

Slide 63

Slide 63 text

RESOURCES , another FP style library stream based library (by the author of async) and , two libraries to bring efficient immutable data structure to js land. Functional programming in js Allong.es highland Immutable Mori

Slide 64

Slide 64 text

Q&A