95
Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Functional Programming – Part II Radu Nicolescu Department of Computer Science University of Auckland 12 Sept 2018 Updated 14 Sept 2018 1 / 53

Functional Programming Part II - Auckland · 2018. 9. 13. · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Functional Programming { Part II Radu Nicolescu

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Functional Programming – Part II

    Radu NicolescuDepartment of Computer Science

    University of Auckland

    12 Sept 2018Updated 14 Sept 2018

    1 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    2 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    3 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition in a nutshell (F#)

    • Forward composition (left-to-right)

    1 l e t h = f 1 >> f 22 l e t h = f 1 >> f 2 >> f 3 . . .

    • Function composition is associative

    1 ( f 1 >> f 2 ) >> f 3 ≡ f 1 >> ( f 2 >> f 3 )

    • Functions must be compatible!

    1 f 1 : ’ a1 −> ’ a22 f 2 : ’ a2 −> ’ a33 f 1 >> f 2 : ’ a1 −> ’ a3

    4 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition in a nutshell (F#)

    • Forward composition (left-to-right)

    1 l e t h = f 1 >> f 22 l e t h = f 1 >> f 2 >> f 3 . . .

    • Function composition is associative

    1 ( f 1 >> f 2 ) >> f 3 ≡ f 1 >> ( f 2 >> f 3 )

    • Functions must be compatible!

    1 f 1 : ’ a1 −> ’ a22 f 2 : ’ a2 −> ’ a33 f 1 >> f 2 : ’ a1 −> ’ a3

    4 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition in a nutshell (F#)

    • Forward composition (left-to-right)

    1 l e t h = f 1 >> f 22 l e t h = f 1 >> f 2 >> f 3 . . .

    • Function composition is associative

    1 ( f 1 >> f 2 ) >> f 3 ≡ f 1 >> ( f 2 >> f 3 )

    • Functions must be compatible!

    1 f 1 : ’ a1 −> ’ a22 f 2 : ’ a2 −> ’ a33 f 1 >> f 2 : ’ a1 −> ’ a3

    4 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipelines in a nutshell (F#)

    • Forward pipeline (left-to-right)

    1 l e t y = x |> f 12 l e t y = x |> f 1 |> f 2 . . .

    • Forward pipelines are left-associative

    1 x |> f 1 |> f 2 ≡ ( x |> f 1 ) |> f 2

    • Again, compatibility required!

    5 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipelines in a nutshell (F#)

    • Forward pipeline (left-to-right)

    1 l e t y = x |> f 12 l e t y = x |> f 1 |> f 2 . . .

    • Forward pipelines are left-associative

    1 x |> f 1 |> f 2 ≡ ( x |> f 1 ) |> f 2

    • Again, compatibility required!

    5 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipelines in a nutshell (F#)

    • Forward pipeline (left-to-right)

    1 l e t y = x |> f 12 l e t y = x |> f 1 |> f 2 . . .

    • Forward pipelines are left-associative

    1 x |> f 1 |> f 2 ≡ ( x |> f 1 ) |> f 2

    • Again, compatibility required!

    5 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition vs Pipelines (F#)

    • Equivalent

    1 l e t y = x |> f 1 |> f 223 l e t y = ( f 1 >> f 2 ) x

    • Definitions?

    6 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition vs Pipelines (F#)

    • Equivalent

    1 l e t y = x |> f 1 |> f 223 l e t y = ( f 1 >> f 2 ) x

    • Definitions?

    6 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Sidebar: operators (F#)

    • Equivalent

    1 l e t ( ∗+) x y = x∗x + y∗y23 l e t a = ( ∗+) 3 44 l e t b = 3 ∗+ 456 p r i n t f n ”%d %d” a b // 25 25

    7 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition and Pipelines: Definitions (F#)

    • Forward composition (left-to-right)

    1 l e t (>>) f g = fun x −> g ( f x )

    • Forward pipeline (left-to-right)

    1 l e t ( |>) x f = f x

    • Reverse composition (right-to-left) – as in maths (f ◦ g)

    1 l e t (

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition and Pipelines: Definitions (F#)

    • Forward composition (left-to-right)

    1 l e t (>>) f g = fun x −> g ( f x )

    • Forward pipeline (left-to-right)

    1 l e t ( |>) x f = f x

    • Reverse composition (right-to-left) – as in maths (f ◦ g)

    1 l e t (

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Forward and Reverse Pipelines (F#)

    • Avoiding extra parentheses

    1 l e t f x y = ( x+1)∗y23 l e t y = f (2+1) (6+1)45 l e t z = 2+1 |> f

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition Samples (F#)

    • Composition Samples (F#)

    1 l e t (>>) f g = fun x −> g ( f x )23 l e t h2 =4 ( fun ( x : s t r i n g ) −> x . Length ) >>5 ( fun y −> ( double y ) / 2 . 0 )6 l e t r2 = h2 ” abc ” // 1 .578 l e t h3 =9 ( fun ( x : s t r i n g ) −> x . Length ) >>

    10 ( fun y −> ( double y ) / 2 . 0 ) >>11 ( fun z −> z +1.0)12 l e t r3 = h3 ” abc ” // 2 .5

    10 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipeline Samples (F#)

    • Pipeline Samples (F#)1 l e t ( |>) x f = f x23 l e t r1 =4 ” abc ”5 |> fun x −> x . Length67 l e t r2 =8 ” abc ”9 |> fun x −> x . Length

    10 |> fun y −> ( double y ) / 2 . 01112 l e t r3 =13 ” abc ”14 |> fun x −> x . Length15 |> fun y −> ( double y ) / 2 . 016 |> fun z −> z +1.0

    11 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    12 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition as high-order function (C#)

    • More complicated than in F# /• Forward composition (left-to-right) as high-order function

    1 Func H ( Func f , Func g ) {2 return x => g ( f ( x ) ) ;3 }

    • Sample1 Func h2 =2 H ( ( s t r i n g x ) => x . Length , y => y / 2 . 0 ) ;3 var r2 = h2 ( ” abc ” ) ; // 1 . 545 Func h3 =6 H (H ( ( s t r i n g x ) => x . Length , y => y / 2 . 0 ) ,7 z => z +1);8 var r3 = h3 ( ” abc ” ) ; // 2 . 5

    13 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition as high-order function (C#)

    • More complicated than in F# /• Forward composition (left-to-right) as high-order function

    1 Func H ( Func f , Func g ) {2 return x => g ( f ( x ) ) ;3 }

    • Sample1 Func h2 =2 H ( ( s t r i n g x ) => x . Length , y => y / 2 . 0 ) ;3 var r2 = h2 ( ” abc ” ) ; // 1 . 545 Func h3 =6 H (H ( ( s t r i n g x ) => x . Length , y => y / 2 . 0 ) ,7 z => z +1);8 var r3 = h3 ( ” abc ” ) ; // 2 . 5

    13 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipeline as high-order function (C#)

    • More complicated than in F# /• Forward pipeline (left-to-right)

    1 B P (A x , Func f ) {2 return f ( x ) ;3 }

    • Sample1 var r1 = P ( ” abc ” , x => x . Length ) ; // 323 var r2 = P (P ( ” abc ” , x => x . Length ) ,4 y => y / 2 . 0 ) ; // 1 . 556 var r3 = P (P (P ( ” abc ” , x => x . Length ) ,7 y => y / 2 . 0 ) ,8 z => z +1); // 2 . 5

    14 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipeline as high-order function (C#)

    • More complicated than in F# /• Forward pipeline (left-to-right)

    1 B P (A x , Func f ) {2 return f ( x ) ;3 }

    • Sample1 var r1 = P ( ” abc ” , x => x . Length ) ; // 323 var r2 = P (P ( ” abc ” , x => x . Length ) ,4 y => y / 2 . 0 ) ; // 1 . 556 var r3 = P (P (P ( ” abc ” , x => x . Length ) ,7 y => y / 2 . 0 ) ,8 z => z +1); // 2 . 5

    14 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipelines – A Better Solution (C#)

    • Extension methods!

    • At the end of this handout

    15 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    16 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition as high-order function (JS)

    • Again, more complicated than in F# /

    • Forward composition (left-to-right) as high-order function

    1 funct ion H ( f , g ) { return x => g ( f ( x ) ) }

    • Sample

    1 l e t h2 =2 H ( x => x . l e n g t h , y => y / 2 . 0 )3 l e t r2 = h2 ( ” abc ” ) // 1 . 545 l e t h3 =6 H (H ( x => x . l e n g t h , y => y / 2 . 0 ) , z => z+1)7 l e t r3 = h3 ( ” abc ” ) // 2 . 5

    17 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition as high-order function (JS)

    • Again, more complicated than in F# /

    • Forward composition (left-to-right) as high-order function

    1 funct ion H ( f , g ) { return x => g ( f ( x ) ) }

    • Sample

    1 l e t h2 =2 H ( x => x . l e n g t h , y => y / 2 . 0 )3 l e t r2 = h2 ( ” abc ” ) // 1 . 545 l e t h3 =6 H (H ( x => x . l e n g t h , y => y / 2 . 0 ) , z => z+1)7 l e t r3 = h3 ( ” abc ” ) // 2 . 5

    17 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipe/Composition as high-order function (JS)

    • “Pipe” from ramda

    • In fact, this “pipe” is a forward composition (left-to-right)1 var R = r e q u i r e ( ’ ramda ’ )

    • Sample1 l e t p1 = R . p i p e ( x => x . l e n g t h )2 l e t r1 = p1 ( ” abc ” ) // 334 l e t p2 = R . p i p e ( x => x . l e n g t h , y => y / 2 . 0 )5 l e t r2 = p2 ( ” abc ” ) // 1 . 567 l e t p3 =8 R . p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)9 l e t r3 = p3 ( ” abc ” ) // 2 . 5

    18 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipe/Composition as high-order function (JS)

    • “Pipe” from ramda

    • In fact, this “pipe” is a forward composition (left-to-right)1 var R = r e q u i r e ( ’ ramda ’ )

    • Sample1 l e t p1 = R . p i p e ( x => x . l e n g t h )2 l e t r1 = p1 ( ” abc ” ) // 334 l e t p2 = R . p i p e ( x => x . l e n g t h , y => y / 2 . 0 )5 l e t r2 = p2 ( ” abc ” ) // 1 . 567 l e t p3 =8 R . p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)9 l e t r3 = p3 ( ” abc ” ) // 2 . 5

    18 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipe/Composition as high-order function (JS)

    • “Pipe” custom definition

    1 const p i p e = ( . . . f u n c s ) =>2 f u n c s . r e d u c e (3 ( acc , c u r r ) => x => c u r r ( acc ( x ) ) , i => i ) ;

    • Will be discussed later (Array.reduce)

    • Sample

    1 l e t p3 =2 p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)3 l e t r 3 = p3 ( ” abc ” ) // 2 . 5

    • Mozilla experimental feature: |> !

    19 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipe/Composition as high-order function (JS)

    • “Pipe” custom definition

    1 const p i p e = ( . . . f u n c s ) =>2 f u n c s . r e d u c e (3 ( acc , c u r r ) => x => c u r r ( acc ( x ) ) , i => i ) ;

    • Will be discussed later (Array.reduce)

    • Sample

    1 l e t p3 =2 p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)3 l e t r 3 = p3 ( ” abc ” ) // 2 . 5

    • Mozilla experimental feature: |> !

    19 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Pipe/Composition as high-order function (JS)

    • “Pipe” custom definition

    1 const p i p e = ( . . . f u n c s ) =>2 f u n c s . r e d u c e (3 ( acc , c u r r ) => x => c u r r ( acc ( x ) ) , i => i ) ;

    • Will be discussed later (Array.reduce)

    • Sample

    1 l e t p3 =2 p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)3 l e t r 3 = p3 ( ” abc ” ) // 2 . 5

    • Mozilla experimental feature: |> !

    19 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    20 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition IF (F#)

    • IF as high-order function

    1 l e t I f ( c , f , g ) =2 fun x −> i f c x then f x e l s e g x

    • Sample

    1 l e t h =2 I f (3 ( fun x −> x%2=1),4 ( fun x −> x +1) ,5 ( fun x −> 2∗x ) )67 l e t r10 = h 10 // 208 l e t r11 = h 11 // 12

    21 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition IF (F#)

    • IF as high-order function

    1 l e t I f ( c , f , g ) =2 fun x −> i f c x then f x e l s e g x

    • Sample

    1 l e t h =2 I f (3 ( fun x −> x%2=1),4 ( fun x −> x +1) ,5 ( fun x −> 2∗x ) )67 l e t r10 = h 10 // 208 l e t r11 = h 11 // 12

    21 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition IF (C#)

    • IF as high-order function1 Func I f (2 Func c ,3 Func f ,4 Func g ) {5 return x => c ( x )? f ( x ) : g ( x ) ;6 }

    • Sample1 var h =2 I f (3 ( i n t x ) => x%2==1,4 ( i n t x ) => x+1,5 ( i n t x ) => 2∗x ) ;67 var r10 = h ( 1 0 ) ; // 208 var r11 = h ( 1 1 ) ; // 12

    22 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition IF (C#)

    • IF as high-order function1 Func I f (2 Func c ,3 Func f ,4 Func g ) {5 return x => c ( x )? f ( x ) : g ( x ) ;6 }

    • Sample1 var h =2 I f (3 ( i n t x ) => x%2==1,4 ( i n t x ) => x+1,5 ( i n t x ) => 2∗x ) ;67 var r10 = h ( 1 0 ) ; // 208 var r11 = h ( 1 1 ) ; // 12

    22 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition IF (JS)

    • IF as high-order function

    1 funct ion I f ( c , f , g ) {2 return x => c ( x ) ? f ( x ) : g ( x )3 }

    • Sample

    1 l e t h =2 I f (3 ( x => x%2===1),4 ( x => x +1) ,5 ( x => 2∗x ) )67 l e t r10 = h ( 1 0 ) // 208 l e t r11 = h ( 1 1 ) // 11

    23 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition IF (JS)

    • IF as high-order function

    1 funct ion I f ( c , f , g ) {2 return x => c ( x ) ? f ( x ) : g ( x )3 }

    • Sample

    1 l e t h =2 I f (3 ( x => x%2===1),4 ( x => x +1) ,5 ( x => 2∗x ) )67 l e t r10 = h ( 1 0 ) // 208 l e t r11 = h ( 1 1 ) // 11

    23 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    24 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (F#)

    • LOOP as high-order function – tail recursive!1 l e t rec Loop ( c , f ) =2 fun x −> i f c ( x ) then Loop ( c , f ) ( f x ) e l s e x

    • Sample1 l e t h =2 Loop (3 ( fun x −> x < 100) ,4 ( fun x −> x + x ) )5 l e t r = h 10 // 160

    • Equivalent1 l e t mutable x ’ = 102 whi le ( x ’ < 100) do3 x ’

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (F#)

    • LOOP as high-order function – tail recursive!1 l e t rec Loop ( c , f ) =2 fun x −> i f c ( x ) then Loop ( c , f ) ( f x ) e l s e x

    • Sample1 l e t h =2 Loop (3 ( fun x −> x < 100) ,4 ( fun x −> x + x ) )5 l e t r = h 10 // 160

    • Equivalent1 l e t mutable x ’ = 102 whi le ( x ’ < 100) do3 x ’

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (F#)

    • LOOP as high-order function – tail recursive!1 l e t rec Loop ( c , f ) =2 fun x −> i f c ( x ) then Loop ( c , f ) ( f x ) e l s e x

    • Sample1 l e t h =2 Loop (3 ( fun x −> x < 100) ,4 ( fun x −> x + x ) )5 l e t r = h 10 // 160

    • Equivalent1 l e t mutable x ’ = 102 whi le ( x ’ < 100) do3 x ’

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (C#)

    • LOOP as high-order function

    1 Func Loop (2 Func c ,3 Func f ) {4 return x => c ( x )? Loop ( c , f ) ( f ( x ) ) : x ;5 }

    • Sample

    1 var h = Loop (2 ( i n t x ) => x < 100 ,3 ( i n t x ) => x + x ) ;4 var r = h ( 1 0 ) ; // 160

    26 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (C#)

    • LOOP as high-order function

    1 Func Loop (2 Func c ,3 Func f ) {4 return x => c ( x )? Loop ( c , f ) ( f ( x ) ) : x ;5 }

    • Sample

    1 var h = Loop (2 ( i n t x ) => x < 100 ,3 ( i n t x ) => x + x ) ;4 var r = h ( 1 0 ) ; // 160

    26 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (JS)

    • LOOP as high-order function

    1 funct ion Loop ( c , f ) {2 return x => c ( x ) ? Loop ( c , f ) ( f ( x ) ) : x3 }

    • Sample

    1 l e t h =2 Loop (3 ( x => x < 100) ,4 ( x => x + x ) )5 l e t r = h ( 1 0 ) // 160

    27 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Composition LOOP (JS)

    • LOOP as high-order function

    1 funct ion Loop ( c , f ) {2 return x => c ( x ) ? Loop ( c , f ) ( f ( x ) ) : x3 }

    • Sample

    1 l e t h =2 Loop (3 ( x => x < 100) ,4 ( x => x + x ) )5 l e t r = h ( 1 0 ) // 160

    27 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    28 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    JS Composition is Type-less

    • In JS you can get runtime type errors after inserting arbitraryobjects in a pipe

    • Typical custom definition:1 const p i p e = ( . . . f u n c s ) =>2 f u n c s . r e d u c e (3 ( acc , c u r r ) => x => c u r r ( acc ( x ) ) , i => i ) ;

    • Sample wrong code...1 l e t p3 = p i p e ( 7 , ” abc ” )2 l e t r 3 = p3 ( )

    • ... which stops with runtime type error1 // TypeEr ror : c u r r i s not a f u n c t i o n

    29 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    C# and F# Compositions are Type-aware

    • NO runtime type errors: only compatible functions can becomposed

    • Explicitly typed C# code:1 Func H ( Func f , Func g ) {2 return x => g ( f ( x ) ) ;3 }

    • Implicitly typed F# code:1 l e t (>>) f g = fun x −> g ( f x )

    • F# types are inferred and can be visualised, e.g. with FSI1 > (>>);;2 ( ( ’ a −> ’ b ) −> ( ’ b −> ’ c ) −> ’ a −> ’ c )

    30 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    F# Composition with explicit types

    • Implicitly typed F# code:

    1 l e t (>>) f g = fun x −> g ( f x )

    • Although not usual, F# types can be made explicit:

    1 l e t (>>) ( f : ’ a−>’b ) ( g : ’ b−>’c ) : ’ a−>’c =2 fun x −> g ( f x )

    31 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    F# Compositions – Types Summary

    • Forward (LR) composition:1 l e t (>>) f g = fun x −> g ( f x )2 // ( ’ a−>’b ) −> ( ’ b−>’c ) −> ’ a −> ’ c

    • Forward (LR) pipe:1 l e t ( |>) x f = f x // ’ a −> ( ’ a−>’b ) −> ’ b

    • IF:1 l e t I f ( c , f , g ) =2 fun x −> i f c x then f x e l s e g x3 // c : ( ’ a−>bool )∗ f : ( ’ a−>’b )∗ g : ( ’ a−>’b ) −> x : ’ a −> ’ b

    • LOOP:1 l e t rec Loop ( c , f ) =2 fun x −> i f c ( x ) then Loop ( c , f ) ( f x ) e l s e x3 // c : ( ’ a−>bool )∗ f : ( ’ a−>’a ) −> x : ’ a −> ’ a

    32 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    33 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying

    Programming technique inspired from mathematical logic,following ideas developed by Moses Schönfinkel and Haskell Curry.

    Problem

    Transform a function with n parameters into a chain of n functionswith one parameter each

    34 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying – Benefits

    • Optimizations are possible by partial evaluation of functions

    • Pipelining is straightforward with functions of one parameter

    • Theoretical proofs are easier with functions of one parameter

    35 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of two parameters

    Given p : A× B → Cdetermine q : A→ (B → C )such that p(x , y) = q(x)(y)

    36 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of two parameters (C#)

    • Sample (where A = B = C = int):

    1 Func p = ( x , y ) => x∗x + y∗y ;2 Func q = x => y => x∗x + y∗y ;3 Func q2 = x => ( y => x∗x + y∗y ) ;

    • Optimised equivalent for q(3)1 Func q ( 3 ) = y => 9 + y∗y ;2 // potentially faster than 3*3 + y*y

    • Usage1 var b = q ( 3 ) ( 4 ) ; // 252 var b2 = q2 ( 3 ) ( 4 ) ; // 2534 Func r = q2 ( 3 ) ;5 var c1 = r ( 4 ) ; // 256 var c2 = r ( 5 ) ; // 34

    37 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of two parameters (C#)

    • Sample (where A = B = C = int):

    1 Func p = ( x , y ) => x∗x + y∗y ;2 Func q = x => y => x∗x + y∗y ;3 Func q2 = x => ( y => x∗x + y∗y ) ;

    • Optimised equivalent for q(3)1 Func q ( 3 ) = y => 9 + y∗y ;2 // potentially faster than 3*3 + y*y

    • Usage1 var b = q ( 3 ) ( 4 ) ; // 252 var b2 = q2 ( 3 ) ( 4 ) ; // 2534 Func r = q2 ( 3 ) ;5 var c1 = r ( 4 ) ; // 256 var c2 = r ( 5 ) ; // 34

    37 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of two parameters (C#)

    • Sample (where A = B = C = int):

    1 Func p = ( x , y ) => x∗x + y∗y ;2 Func q = x => y => x∗x + y∗y ;3 Func q2 = x => ( y => x∗x + y∗y ) ;

    • Optimised equivalent for q(3)1 Func q ( 3 ) = y => 9 + y∗y ;2 // potentially faster than 3*3 + y*y

    • Usage1 var b = q ( 3 ) ( 4 ) ; // 252 var b2 = q2 ( 3 ) ( 4 ) ; // 2534 Func r = q2 ( 3 ) ;5 var c1 = r ( 4 ) ; // 256 var c2 = r ( 5 ) ; // 34

    37 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of two parameters (JS)

    • Sample

    1 l e t p = ( x , y ) => x∗x + y∗y23 l e t q = x => y => x∗x + y∗y4 l e t q2 = x => ( y => p ( x , y ) )

    • Usage

    1 l e t b = q ( 3 ) ( 4 )2 l e t b2 = q2 ( 3 ) ( 4 )34 l e t r = q ( 3 )5 l e t c1 = r ( 4 )6 l e t c2 = r ( 5 )

    38 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of two parameters (JS)

    • Sample

    1 l e t p = ( x , y ) => x∗x + y∗y23 l e t q = x => y => x∗x + y∗y4 l e t q2 = x => ( y => p ( x , y ) )

    • Usage

    1 l e t b = q ( 3 ) ( 4 )2 l e t b2 = q2 ( 3 ) ( 4 )34 l e t r = q ( 3 )5 l e t c1 = r ( 4 )6 l e t c2 = r ( 5 )

    38 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of “two” parameters (F#)

    • Sample1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y34 // q : i n t −> i n t −> i n t5 l e t q = fun x −> fun y −> x∗x + y∗y6 l e t q ’ = fun x −> ( fun y −> p ( x , y ) )

    • Usage1 l e t b = q 3 42 l e t b ’ = q ’ 3 434 // r : i n t −> i n t5 l e t r = q 36 l e t c1 = r 47 l e t c2 = r 5

    39 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of “two” parameters (F#)

    • Sample1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y34 // q : i n t −> i n t −> i n t5 l e t q = fun x −> fun y −> x∗x + y∗y6 l e t q ’ = fun x −> ( fun y −> p ( x , y ) )

    • Usage1 l e t b = q 3 42 l e t b ’ = q ’ 3 434 // r : i n t −> i n t5 l e t r = q 36 l e t c1 = r 47 l e t c2 = r 5

    39 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of “two” parameters (F#)?

    • All F# functions have one single parameter!• This function has one single parameter, which is a tuple

    1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y

    • Example: function that returns a function (chained functions)

    1 // q ’ ’ : i n t −> i n t −> i n t2 l e t q ’ ’ x y = x∗x + y∗y

    • Equivalent function:

    1 // q : i n t −> i n t −> i n t2 l e t q = fun x −> fun y −> x∗x + y∗y

    40 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of “two” parameters (F#)?

    • All F# functions have one single parameter!• This function has one single parameter, which is a tuple

    1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y

    • Example: function that returns a function (chained functions)

    1 // q ’ ’ : i n t −> i n t −> i n t2 l e t q ’ ’ x y = x∗x + y∗y

    • Equivalent function:

    1 // q : i n t −> i n t −> i n t2 l e t q = fun x −> fun y −> x∗x + y∗y

    40 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of “two” parameters (F#)?

    • All F# functions have one single parameter!• This function has one single parameter, which is a tuple

    1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y

    • Example: function that returns a function (chained functions)

    1 // q ’ ’ : i n t −> i n t −> i n t2 l e t q ’ ’ x y = x∗x + y∗y

    • Equivalent function:

    1 // q : i n t −> i n t −> i n t2 l e t q = fun x −> fun y −> x∗x + y∗y

    40 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of three parameters (C#)

    Given q : A× B × C → Ddetermine q1 : A→ (B → (C → D))such that q(x , y , z) = q1(x)(y)(z)

    Example (where A = B = C = D = int):

    1 Func2 q = ( x , y , z ) => x∗x + y∗y + z∗ z ;

    1 Func2 q1 = x => ( y => ( z => x∗x + y∗y + z∗ z ) ) ;

    1 q1 ( 1 0 ) ( 2 0 ) = z => 500 + z ;2 // potentially faster than 10*10 + 20*20 + z*z

    41 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of three parameters (C#)

    Given q : A× B × C → Ddetermine q1 : A→ (B → (C → D))such that q(x , y , z) = q1(x)(y)(z)

    Example (where A = B = C = D = int):

    1 Func2 q = ( x , y , z ) => x∗x + y∗y + z∗ z ;

    1 Func2 q1 = x => ( y => ( z => x∗x + y∗y + z∗ z ) ) ;

    1 q1 ( 1 0 ) ( 2 0 ) = z => 500 + z ;2 // potentially faster than 10*10 + 20*20 + z*z

    41 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of three parameters (C#)

    Given q : A× B × C → Ddetermine q1 : A→ (B → (C → D))such that q(x , y , z) = q1(x)(y)(z)

    Example (where A = B = C = D = int):

    1 Func2 q = ( x , y , z ) => x∗x + y∗y + z∗ z ;

    1 Func2 q1 = x => ( y => ( z => x∗x + y∗y + z∗ z ) ) ;

    1 q1 ( 1 0 ) ( 2 0 ) = z => 500 + z ;2 // potentially faster than 10*10 + 20*20 + z*z

    41 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Currying a function of three parameters (C#)

    Given q : A× B × C → Ddetermine q1 : A→ (B → (C → D))such that q(x , y , z) = q1(x)(y)(z)

    Example (where A = B = C = D = int):

    1 Func2 q = ( x , y , z ) => x∗x + y∗y + z∗ z ;

    1 Func2 q1 = x => ( y => ( z => x∗x + y∗y + z∗ z ) ) ;

    1 q1 ( 1 0 ) ( 2 0 ) = z => 500 + z ;2 // potentially faster than 10*10 + 20*20 + z*z

    41 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    42 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods in a Nutshell (C#)

    • Retrofitting F#-style pipes in C#, an initially OO language

    • F# pipeline of functions

    1 s |> Foo |> Goo |> Hoo

    • C# simulation via cascading/fluent method chaining

    1 s . Foo ( ) . Goo ( ) . Hoo ( )

    • It seems that we have to extend existing classes...but these may be sealed ( final in Java) /

    • Extension methods come to the rescue ,

    43 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods in a Nutshell (C#)

    • Retrofitting F#-style pipes in C#, an initially OO language

    • F# pipeline of functions

    1 s |> Foo |> Goo |> Hoo

    • C# simulation via cascading/fluent method chaining

    1 s . Foo ( ) . Goo ( ) . Hoo ( )

    • It seems that we have to extend existing classes...but these may be sealed ( final in Java) /

    • Extension methods come to the rescue ,

    43 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods in a Nutshell (C#)

    • Retrofitting F#-style pipes in C#, an initially OO language

    • F# pipeline of functions

    1 s |> Foo |> Goo |> Hoo

    • C# simulation via cascading/fluent method chaining

    1 s . Foo ( ) . Goo ( ) . Hoo ( )

    • It seems that we have to extend existing classes...but these may be sealed ( final in Java) /

    • Extension methods come to the rescue ,

    43 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods in a Nutshell (C#)

    • Retrofitting F#-style pipes in C#, an initially OO language

    • F# pipeline of functions

    1 s |> Foo |> Goo |> Hoo

    • C# simulation via cascading/fluent method chaining

    1 s . Foo ( ) . Goo ( ) . Hoo ( )

    • It seems that we have to extend existing classes...but these may be sealed ( final in Java) /

    • Extension methods come to the rescue ,

    43 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods (C#)

    An extension method:

    • Is defined as a static method

    • appears in a class decorated as static (see below)

    • its first parameter is decorated with this

    • despite being static, can also be can be called in instancenotation, where its first parameter appears as its target

    A static class is equivalent to a sealed class with a privateconstructor: therefore, you can’t subclass it and you can’tinstantiate it! Its only purpose is to define extension methods.

    44 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods (C#)

    An extension method:

    • Is defined as a static method

    • appears in a class decorated as static (see below)

    • its first parameter is decorated with this

    • despite being static, can also be can be called in instancenotation, where its first parameter appears as its target

    A static class is equivalent to a sealed class with a privateconstructor: therefore, you can’t subclass it and you can’tinstantiate it! Its only purpose is to define extension methods.

    44 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods (C#)

    An extension method:

    • Is defined as a static method

    • appears in a class decorated as static (see below)

    • its first parameter is decorated with this

    • despite being static, can also be can be called in instancenotation, where its first parameter appears as its target

    A static class is equivalent to a sealed class with a privateconstructor: therefore, you can’t subclass it and you can’tinstantiate it! Its only purpose is to define extension methods.

    44 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods (C#)

    An extension method:

    • Is defined as a static method

    • appears in a class decorated as static (see below)

    • its first parameter is decorated with this

    • despite being static, can also be can be called in instancenotation, where its first parameter appears as its target

    A static class is equivalent to a sealed class with a privateconstructor: therefore, you can’t subclass it and you can’tinstantiate it! Its only purpose is to define extension methods.

    44 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension Methods (C#)

    An extension method:

    • Is defined as a static method

    • appears in a class decorated as static (see below)

    • its first parameter is decorated with this

    • despite being static, can also be can be called in instancenotation, where its first parameter appears as its target

    A static class is equivalent to a sealed class with a privateconstructor: therefore, you can’t subclass it and you can’tinstantiate it! Its only purpose is to define extension methods.

    44 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    Consider that we want to “extend” the (already sealed) Systemclass string with a new method bool Foo(int).

    1 var b = ” abc ” . Foo ( 7 ) ; // ???

    We cannot really extend class string, because it is sealed (whichcorresponds to final in Java)...

    However, we can “emulate” such an extension as a static methodin a static class:

    1 static c l a s s MyExtens ions {2 static bool Foo (this s t r i n g s , i n t i ) {3 . . .4 }5 }

    45 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    Consider that we want to “extend” the (already sealed) Systemclass string with a new method bool Foo(int).

    1 var b = ” abc ” . Foo ( 7 ) ; // ???

    We cannot really extend class string, because it is sealed (whichcorresponds to final in Java)...

    However, we can “emulate” such an extension as a static methodin a static class:

    1 static c l a s s MyExtens ions {2 static bool Foo (this s t r i n g s , i n t i ) {3 . . .4 }5 }

    45 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    Consider that we want to “extend” the (already sealed) Systemclass string with a new method bool Foo(int).

    1 var b = ” abc ” . Foo ( 7 ) ; // ???

    We cannot really extend class string, because it is sealed (whichcorresponds to final in Java)...

    However, we can “emulate” such an extension as a static methodin a static class:

    1 static c l a s s MyExtens ions {2 static bool Foo (this s t r i n g s , i n t i ) {3 . . .4 }5 }

    45 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    We can invoke Foo either as a static method, or as an instancemethod for a string object!

    1 s t r i n g s = ” abc ” ;23 var b1 = MyExtens ions . Foo ( s , 7 ) ; // static call45 var b2 = s . Foo ( 7 ) ; // ”instance”-like call

    For the second version (instance-like call), the compiler will searchfor an appropriate method in all available static classes (this limitsthe scope of the search)

    46 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    We can invoke Foo either as a static method, or as an instancemethod for a string object!

    1 s t r i n g s = ” abc ” ;23 var b1 = MyExtens ions . Foo ( s , 7 ) ; // static call45 var b2 = s . Foo ( 7 ) ; // ”instance”-like call

    For the second version (instance-like call), the compiler will searchfor an appropriate method in all available static classes (this limitsthe scope of the search)

    46 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    The instance notation is convenient for composing functions in afluent method chaining, i.e. cascading transformations (whichleads to crisp expressions) – similar to Unix-like pipelines

    For example, besides Foo, assume a couple of other similarmethods, Goo and Hoo. Contrast the following two equivalentcalls, comparing them for expressiveness:

    1 var b1 =2 MyExtens ions . Hoo (3 MyExtens ions . Goo (4 MyExtens ions . Foo ( s , 1 ) , 2 ) , 3 ) ;56 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

    Most functional elements in C# and LINQ are actually defined asextension methods!

    47 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    The instance notation is convenient for composing functions in afluent method chaining, i.e. cascading transformations (whichleads to crisp expressions) – similar to Unix-like pipelines

    For example, besides Foo, assume a couple of other similarmethods, Goo and Hoo. Contrast the following two equivalentcalls, comparing them for expressiveness:

    1 var b1 =2 MyExtens ions . Hoo (3 MyExtens ions . Goo (4 MyExtens ions . Foo ( s , 1 ) , 2 ) , 3 ) ;56 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

    Most functional elements in C# and LINQ are actually defined asextension methods!

    47 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – sample

    The instance notation is convenient for composing functions in afluent method chaining, i.e. cascading transformations (whichleads to crisp expressions) – similar to Unix-like pipelines

    For example, besides Foo, assume a couple of other similarmethods, Goo and Hoo. Contrast the following two equivalentcalls, comparing them for expressiveness:

    1 var b1 =2 MyExtens ions . Hoo (3 MyExtens ions . Goo (4 MyExtens ions . Foo ( s , 1 ) , 2 ) , 3 ) ;56 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

    Most functional elements in C# and LINQ are actually defined asextension methods!

    47 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Extension method (C#) – caveat

    Caveat: in C#, extensions methods, such as Foo, are not realinstance methods:

    • Cannot access private members

    • Cannot be polymorphically overridden

    48 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Outline

    1 Composition and Pipelining (F#)

    2 Composition and Pipelining (C#)

    3 Composition and Pipelining (JS)

    4 Composition IF

    5 Composition LOOP

    6 Composition and Types

    7 Currying and Partial Application

    8 Extension Methods (C#)

    9 Recursion

    49 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Recursion in FP

    Non-tail recursive factorial in F#:

    1 l e t rec f a c t ( n : i n t ) =2 i f ( n

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Recursion in FP

    Non-tail recursive factorial in F#:

    1 l e t rec f a c t ( n : i n t ) =2 i f ( n

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Recursion in FP

    Tail recursive factorial in F# – efficient! immutable values!

    1 l e t rec f a c t t a i l r e c ( n : int , acc : i n t ) =2 i f ( n 0) {3 i n t n1 = n − 1 ;4 acc = n ∗ acc ;5 n = n1 ;6 }7 return acc ;8 }

    51 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Recursion in FP

    Tail recursive factorial in F# – efficient! immutable values!

    1 l e t rec f a c t t a i l r e c ( n : int , acc : i n t ) =2 i f ( n 0) {3 i n t n1 = n − 1 ;4 acc = n ∗ acc ;5 n = n1 ;6 }7 return acc ;8 }

    51 / 53

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Recursion in FP

    Why avoid recursion?

    • Easy to define correct but inefficient algorithms (unless we usememoization or other optimisations)

    1 // combinatorial explosion2 i n t Fib ( i n t n ) {3 i f ( n

  • Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

    Recursion in FP

    Why use recursion in FP?

    • To define correct and efficient algorithms (via memoization orother optimisations)

    • To use immutable values only (avoid changing the values ofvariables)

    • Efficient implementation of tail calls, which are automaticallytransformed into loops

    53 / 53

    Composition and Pipelining (F#)Composition and Pipelining (C#)Composition and Pipelining (JS)Composition IFComposition LOOPComposition and TypesCurrying and Partial ApplicationExtension Methods (C#)Recursion