Functional Programming Part II Radu Nicolescu Department of - - PowerPoint PPT Presentation

functional programming part ii
SMART_READER_LITE
LIVE PREVIEW

Functional Programming Part II Radu Nicolescu Department of - - PowerPoint PPT Presentation

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 Comp (F#) Comp


slide-1
SLIDE 1

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

slide-2
SLIDE 2

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

slide-3
SLIDE 3

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

slide-4
SLIDE 4

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 = f1 >> f2 2 l e t h = f1 >> f2 >> f3 . . .

  • Function composition is associative

1 ( f1 >> f2 ) >> f3 ≡ f1 >> ( f2 >> f3 )

  • Functions must be compatible!

1 f1 : ’ a1 −> ’ a2 2 f2 : ’ a2 −> ’ a3 3 f1 >> f2 : ’ a1 −> ’ a3

4 / 53

slide-5
SLIDE 5

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 = f1 >> f2 2 l e t h = f1 >> f2 >> f3 . . .

  • Function composition is associative

1 ( f1 >> f2 ) >> f3 ≡ f1 >> ( f2 >> f3 )

  • Functions must be compatible!

1 f1 : ’ a1 −> ’ a2 2 f2 : ’ a2 −> ’ a3 3 f1 >> f2 : ’ a1 −> ’ a3

4 / 53

slide-6
SLIDE 6

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 = f1 >> f2 2 l e t h = f1 >> f2 >> f3 . . .

  • Function composition is associative

1 ( f1 >> f2 ) >> f3 ≡ f1 >> ( f2 >> f3 )

  • Functions must be compatible!

1 f1 : ’ a1 −> ’ a2 2 f2 : ’ a2 −> ’ a3 3 f1 >> f2 : ’ a1 −> ’ a3

4 / 53

slide-7
SLIDE 7

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 |> f1 2 l e t y = x |> f1 |> f2 . . .

  • Forward pipelines are left-associative

1 x |> f1 |> f2 ≡ ( x |> f1 ) |> f2

  • Again, compatibility required!

5 / 53

slide-8
SLIDE 8

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 |> f1 2 l e t y = x |> f1 |> f2 . . .

  • Forward pipelines are left-associative

1 x |> f1 |> f2 ≡ ( x |> f1 ) |> f2

  • Again, compatibility required!

5 / 53

slide-9
SLIDE 9

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 |> f1 2 l e t y = x |> f1 |> f2 . . .

  • Forward pipelines are left-associative

1 x |> f1 |> f2 ≡ ( x |> f1 ) |> f2

  • Again, compatibility required!

5 / 53

slide-10
SLIDE 10

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

Composition vs Pipelines (F#)

  • Equivalent

1 l e t y = x |> f1 |> f2 2 3 l e t y = ( f1 >> f2 ) x

  • Definitions?

6 / 53

slide-11
SLIDE 11

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

Composition vs Pipelines (F#)

  • Equivalent

1 l e t y = x |> f1 |> f2 2 3 l e t y = ( f1 >> f2 ) x

  • Definitions?

6 / 53

slide-12
SLIDE 12

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∗y 2 3 l e t a = ( ∗+) 3 4 4 l e t b = 3 ∗+ 4 5 6 printfn ”%d %d” a b // 25 25

7 / 53

slide-13
SLIDE 13

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 (<<) f g = fun x −> f ( g x )

  • Reverse pipeline (right-to-left) – sometimes useful

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

8 / 53

slide-14
SLIDE 14

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 (<<) f g = fun x −> f ( g x )

  • Reverse pipeline (right-to-left) – sometimes useful

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

8 / 53

slide-15
SLIDE 15

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)∗y 2 3 l e t y = f (2+1) (6+1) 4 5 l e t z = 2+1 |> f <| 6+1 6 7 printfn ”%d %d” y z

9 / 53

slide-16
SLIDE 16

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 ) 2 3 l e t h2 = 4 ( fun ( x : string ) −> x . Length ) >> 5 ( fun y −> ( double y )/2.0 ) 6 l e t r2 = h2 ”abc” // 1.5 7 8 l e t h3 = 9 ( fun ( x : string ) −> 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

slide-17
SLIDE 17

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 x 2 3 l e t r1 = 4 ”abc” 5 |> fun x −> x . Length 6 7 l e t r2 = 8 ”abc” 9 |> fun x −> x . Length 10 |> fun y −> ( double y )/2.0 11 12 l e t r3 = 13 ”abc” 14 |> fun x −> x . Length 15 |> fun y −> ( double y )/2.0 16 |> fun z −> z +1.0

11 / 53

slide-18
SLIDE 18

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

slide-19
SLIDE 19

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<A,C> H <A,B,C> ( Func<A,B> f , Func<B,C> g ) { 2 return x = > g ( f ( x ) ) ; 3 }

  • Sample

1 Func<string , double> h2 = 2 H (( string x ) = > x . Length , y = > y / 2 . 0 ) ; 3 var r2 = h2 ( ”abc” ) ; // 1.5 4 5 Func<string , double> h3 = 6 H (H (( string x ) = > x . Length , y = > y /2.0) , 7 z = > z +1); 8 var r3 = h3 ( ”abc” ) ; // 2.5

13 / 53

slide-20
SLIDE 20

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<A,C> H <A,B,C> ( Func<A,B> f , Func<B,C> g ) { 2 return x = > g ( f ( x ) ) ; 3 }

  • Sample

1 Func<string , double> h2 = 2 H (( string x ) = > x . Length , y = > y / 2 . 0 ) ; 3 var r2 = h2 ( ”abc” ) ; // 1.5 4 5 Func<string , double> h3 = 6 H (H (( string x ) = > x . Length , y = > y /2.0) , 7 z = > z +1); 8 var r3 = h3 ( ”abc” ) ; // 2.5

13 / 53

slide-21
SLIDE 21

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,B> (A x , Func<A,B> f ) { 2 return f ( x ) ; 3 }

  • Sample

1 var r1 = P ( ”abc” , x = > x . Length ) ; // 3 2 3 var r2 = P (P ( ”abc” , x = > x . Length ) , 4 y = > y / 2 . 0 ) ; // 1.5 5 6 var r3 = P (P (P ( ”abc” , x = > x . Length ) , 7 y = > y /2.0) , 8 z = > z +1); // 2.5

14 / 53

slide-22
SLIDE 22

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,B> (A x , Func<A,B> f ) { 2 return f ( x ) ; 3 }

  • Sample

1 var r1 = P ( ”abc” , x = > x . Length ) ; // 3 2 3 var r2 = P (P ( ”abc” , x = > x . Length ) , 4 y = > y / 2 . 0 ) ; // 1.5 5 6 var r3 = P (P (P ( ”abc” , x = > x . Length ) , 7 y = > y /2.0) , 8 z = > z +1); // 2.5

14 / 53

slide-23
SLIDE 23

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

slide-24
SLIDE 24

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

slide-25
SLIDE 25

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 function H ( f , g ) { return x = > g ( f ( x )) }

  • Sample

1 l e t h2 = 2 H ( x = > x . length , y = > y /2.0) 3 l e t r2 = h2 ( ”abc” ) // 1.5 4 5 l e t h3 = 6 H (H ( x = > x . length , y = > y /2.0) , z = > z+1) 7 l e t r3 = h3 ( ”abc” ) // 2.5

17 / 53

slide-26
SLIDE 26

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 function H ( f , g ) { return x = > g ( f ( x )) }

  • Sample

1 l e t h2 = 2 H ( x = > x . length , y = > y /2.0) 3 l e t r2 = h2 ( ”abc” ) // 1.5 4 5 l e t h3 = 6 H (H ( x = > x . length , y = > y /2.0) , z = > z+1) 7 l e t r3 = h3 ( ”abc” ) // 2.5

17 / 53

slide-27
SLIDE 27

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 ’ )

  • Sample

1 l e t p1 = R. pipe ( x = > x . length ) 2 l e t r1 = p1 ( ”abc” ) // 3 3 4 l e t p2 = R. pipe ( x = > x . length , y = > y /2.0) 5 l e t r2 = p2 ( ”abc” ) // 1.5 6 7 l e t p3 = 8

  • R. pipe

( x = > x . length , y = > y /2.0 , z = > z+1) 9 l e t r3 = p3 ( ”abc” ) // 2.5

18 / 53

slide-28
SLIDE 28

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 ’ )

  • Sample

1 l e t p1 = R. pipe ( x = > x . length ) 2 l e t r1 = p1 ( ”abc” ) // 3 3 4 l e t p2 = R. pipe ( x = > x . length , y = > y /2.0) 5 l e t r2 = p2 ( ”abc” ) // 1.5 6 7 l e t p3 = 8

  • R. pipe

( x = > x . length , y = > y /2.0 , z = > z+1) 9 l e t r3 = p3 ( ”abc” ) // 2.5

18 / 53

slide-29
SLIDE 29

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 = ( . . . funcs ) = > 2 funcs . reduce ( 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 . length , y = > y /2.0 , z = > z+1) 3 l e t r 3 = p3 ( ”abc” ) // 2.5

  • Mozilla experimental feature: |> !

19 / 53

slide-30
SLIDE 30

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 = ( . . . funcs ) = > 2 funcs . reduce ( 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 . length , y = > y /2.0 , z = > z+1) 3 l e t r 3 = p3 ( ”abc” ) // 2.5

  • Mozilla experimental feature: |> !

19 / 53

slide-31
SLIDE 31

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 = ( . . . funcs ) = > 2 funcs . reduce ( 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 . length , y = > y /2.0 , z = > z+1) 3 l e t r 3 = p3 ( ”abc” ) // 2.5

  • Mozilla experimental feature: |> !

19 / 53

slide-32
SLIDE 32

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

slide-33
SLIDE 33

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 else 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 )) 6 7 l e t r10 = h 10 // 20 8 l e t r11 = h 11 // 12

21 / 53

slide-34
SLIDE 34

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 else 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 )) 6 7 l e t r10 = h 10 // 20 8 l e t r11 = h 11 // 12

21 / 53

slide-35
SLIDE 35

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

Composition IF (C#)

  • IF as high-order function

1 Func<A,B> I f <A,B> ( 2 Func<A, bool> c , 3 Func<A,B> f , 4 Func<A,B> g ) { 5 return x = > c ( x )? f ( x ) : g ( x ) ; 6 }

  • Sample

1 var h = 2 I f ( 3 ( int x ) = > x%2==1, 4 ( int x ) = > x+1, 5 ( int x ) = > 2∗x ) ; 6 7 var r10 = h ( 1 0 ) ; // 20 8 var r11 = h ( 1 1 ) ; // 12

22 / 53

slide-36
SLIDE 36

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

Composition IF (C#)

  • IF as high-order function

1 Func<A,B> I f <A,B> ( 2 Func<A, bool> c , 3 Func<A,B> f , 4 Func<A,B> g ) { 5 return x = > c ( x )? f ( x ) : g ( x ) ; 6 }

  • Sample

1 var h = 2 I f ( 3 ( int x ) = > x%2==1, 4 ( int x ) = > x+1, 5 ( int x ) = > 2∗x ) ; 6 7 var r10 = h ( 1 0 ) ; // 20 8 var r11 = h ( 1 1 ) ; // 12

22 / 53

slide-37
SLIDE 37

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

Composition IF (JS)

  • IF as high-order function

1 function 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 )) 6 7 l e t r10 = h (10) // 20 8 l e t r11 = h (11) // 11

23 / 53

slide-38
SLIDE 38

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

Composition IF (JS)

  • IF as high-order function

1 function 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 )) 6 7 l e t r10 = h (10) // 20 8 l e t r11 = h (11) // 11

23 / 53

slide-39
SLIDE 39

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

slide-40
SLIDE 40

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 ) else x

  • Sample

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

  • Equivalent

1 l e t mutable x ’ = 10 2 while ( x ’ < 100) do 3 x ’ <− x ’ + x ’

25 / 53

slide-41
SLIDE 41

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 ) else x

  • Sample

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

  • Equivalent

1 l e t mutable x ’ = 10 2 while ( x ’ < 100) do 3 x ’ <− x ’ + x ’

25 / 53

slide-42
SLIDE 42

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 ) else x

  • Sample

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

  • Equivalent

1 l e t mutable x ’ = 10 2 while ( x ’ < 100) do 3 x ’ <− x ’ + x ’

25 / 53

slide-43
SLIDE 43

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

Composition LOOP (C#)

  • LOOP as high-order function

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

  • Sample

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

26 / 53

slide-44
SLIDE 44

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

Composition LOOP (C#)

  • LOOP as high-order function

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

  • Sample

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

26 / 53

slide-45
SLIDE 45

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

Composition LOOP (JS)

  • LOOP as high-order function

1 function Loop ( c , f ) { 2 return x = > c ( x ) ? Loop ( c , f ) ( f ( x )) : x 3 }

  • Sample

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

27 / 53

slide-46
SLIDE 46

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

Composition LOOP (JS)

  • LOOP as high-order function

1 function Loop ( c , f ) { 2 return x = > c ( x ) ? Loop ( c , f ) ( f ( x )) : x 3 }

  • Sample

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

27 / 53

slide-47
SLIDE 47

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

slide-48
SLIDE 48

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 arbitrary
  • bjects in a pipe
  • Typical custom definition:

1 const p i p e = ( . . . funcs ) = > 2 funcs . reduce ( 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 error

1 // TypeError : c u r r i s not a f u n c t i o n

29 / 53

slide-49
SLIDE 49

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 be

composed

  • Explicitly typed C# code:

1 Func<A,C> H <A,B,C> ( Func<A,B> f , Func<B,C> 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 FSI

1 > ( > >);; 2 (( ’ a −> ’b) −> ( ’ b −> ’ c ) −> ’ a −> ’ c )

30 / 53

slide-50
SLIDE 50

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

slide-51
SLIDE 51

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 else g x 3 // 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 ) else x 3 // c : ( ’ a− >bool )∗ f : ( ’ a−>’a ) −> x : ’ a −> ’ a

32 / 53

slide-52
SLIDE 52

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

slide-53
SLIDE 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 functions with one parameter each

34 / 53

slide-54
SLIDE 54

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

slide-55
SLIDE 55

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

Currying a function of two parameters

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

36 / 53

slide-56
SLIDE 56

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<int , int , int> p = ( x , y ) = > x∗x + y∗y ; 2 Func<int , Func<int , int> > q = x = > y = > x∗x + y∗y ; 3 Func<int , Func<int , int> > q2 = x = > ( y = > x∗x + y∗y ) ;

  • Optimised equivalent for q(3)

1 Func<int , int> q (3) = y = > 9 + y∗y ; 2 // potentially faster than 3*3 + y*y

  • Usage

1 var b = q (3) ( 4 ) ; // 25 2 var b2 = q2 (3) ( 4 ) ; // 25 3 4 Func<int , int> r = q2 ( 3 ) ; 5 var c1 = r ( 4 ) ; // 25 6 var c2 = r ( 5 ) ; // 34

37 / 53

slide-57
SLIDE 57

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<int , int , int> p = ( x , y ) = > x∗x + y∗y ; 2 Func<int , Func<int , int> > q = x = > y = > x∗x + y∗y ; 3 Func<int , Func<int , int> > q2 = x = > ( y = > x∗x + y∗y ) ;

  • Optimised equivalent for q(3)

1 Func<int , int> q (3) = y = > 9 + y∗y ; 2 // potentially faster than 3*3 + y*y

  • Usage

1 var b = q (3) ( 4 ) ; // 25 2 var b2 = q2 (3) ( 4 ) ; // 25 3 4 Func<int , int> r = q2 ( 3 ) ; 5 var c1 = r ( 4 ) ; // 25 6 var c2 = r ( 5 ) ; // 34

37 / 53

slide-58
SLIDE 58

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<int , int , int> p = ( x , y ) = > x∗x + y∗y ; 2 Func<int , Func<int , int> > q = x = > y = > x∗x + y∗y ; 3 Func<int , Func<int , int> > q2 = x = > ( y = > x∗x + y∗y ) ;

  • Optimised equivalent for q(3)

1 Func<int , int> q (3) = y = > 9 + y∗y ; 2 // potentially faster than 3*3 + y*y

  • Usage

1 var b = q (3) ( 4 ) ; // 25 2 var b2 = q2 (3) ( 4 ) ; // 25 3 4 Func<int , int> r = q2 ( 3 ) ; 5 var c1 = r ( 4 ) ; // 25 6 var c2 = r ( 5 ) ; // 34

37 / 53

slide-59
SLIDE 59

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∗y 2 3 l e t q = x = > y = > x∗x + y∗y 4 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) 3 4 l e t r = q (3) 5 l e t c1 = r (4) 6 l e t c2 = r (5)

38 / 53

slide-60
SLIDE 60

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∗y 2 3 l e t q = x = > y = > x∗x + y∗y 4 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) 3 4 l e t r = q (3) 5 l e t c1 = r (4) 6 l e t c2 = r (5)

38 / 53

slide-61
SLIDE 61

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

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

  • Sample

1 // p : int ∗ int −> int 2 l e t p = fun ( x , y ) −> x∗x + y∗y 3 4 // q : int −> int −> int 5 l e t q = fun x −> fun y −> x∗x + y∗y 6 l e t q ’ = fun x −> ( fun y −> p( x , y ))

  • Usage

1 l e t b = q 3 4 2 l e t b ’ = q ’ 3 4 3 4 // r : int −> int 5 l e t r = q 3 6 l e t c1 = r 4 7 l e t c2 = r 5

39 / 53

slide-62
SLIDE 62

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

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

  • Sample

1 // p : int ∗ int −> int 2 l e t p = fun ( x , y ) −> x∗x + y∗y 3 4 // q : int −> int −> int 5 l e t q = fun x −> fun y −> x∗x + y∗y 6 l e t q ’ = fun x −> ( fun y −> p( x , y ))

  • Usage

1 l e t b = q 3 4 2 l e t b ’ = q ’ 3 4 3 4 // r : int −> int 5 l e t r = q 3 6 l e t c1 = r 4 7 l e t c2 = r 5

39 / 53

slide-63
SLIDE 63

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 : int ∗ int −> int 2 l e t p = fun ( x , y ) −> x∗x + y∗y

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

1 // q ’ ’ : int −> int −> int 2 l e t q ’ ’ x y = x∗x + y∗y

  • Equivalent function:

1 // q : int −> int −> int 2 l e t q = fun x −> fun y −> x∗x + y∗y

40 / 53

slide-64
SLIDE 64

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 : int ∗ int −> int 2 l e t p = fun ( x , y ) −> x∗x + y∗y

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

1 // q ’ ’ : int −> int −> int 2 l e t q ’ ’ x y = x∗x + y∗y

  • Equivalent function:

1 // q : int −> int −> int 2 l e t q = fun x −> fun y −> x∗x + y∗y

40 / 53

slide-65
SLIDE 65

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 : int ∗ int −> int 2 l e t p = fun ( x , y ) −> x∗x + y∗y

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

1 // q ’ ’ : int −> int −> int 2 l e t q ’ ’ x y = x∗x + y∗y

  • Equivalent function:

1 // q : int −> int −> int 2 l e t q = fun x −> fun y −> x∗x + y∗y

40 / 53

slide-66
SLIDE 66

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 → D determine q1 : A → (B → (C → D)) such that q(x, y, z) = q1(x)(y)(z) Example (where A = B = C = D = int):

1 Func<int , int , int , int> 2 q = ( x , y , z ) = > x∗x + y∗y + z∗z ; 1 Func<int , Func<int , Func<int , int> > > 2 q1 = x = > ( y = > ( z = > x∗x + y∗y + z∗z ) ) ; 1 q1 (10)(20) = z = > 500 + z ; 2 // potentially faster than 10*10 + 20*20 + z*z

41 / 53

slide-67
SLIDE 67

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 → D determine q1 : A → (B → (C → D)) such that q(x, y, z) = q1(x)(y)(z) Example (where A = B = C = D = int):

1 Func<int , int , int , int> 2 q = ( x , y , z ) = > x∗x + y∗y + z∗z ; 1 Func<int , Func<int , Func<int , int> > > 2 q1 = x = > ( y = > ( z = > x∗x + y∗y + z∗z ) ) ; 1 q1 (10)(20) = z = > 500 + z ; 2 // potentially faster than 10*10 + 20*20 + z*z

41 / 53

slide-68
SLIDE 68

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 → D determine q1 : A → (B → (C → D)) such that q(x, y, z) = q1(x)(y)(z) Example (where A = B = C = D = int):

1 Func<int , int , int , int> 2 q = ( x , y , z ) = > x∗x + y∗y + z∗z ; 1 Func<int , Func<int , Func<int , int> > > 2 q1 = x = > ( y = > ( z = > x∗x + y∗y + z∗z ) ) ; 1 q1 (10)(20) = z = > 500 + z ; 2 // potentially faster than 10*10 + 20*20 + z*z

41 / 53

slide-69
SLIDE 69

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 → D determine q1 : A → (B → (C → D)) such that q(x, y, z) = q1(x)(y)(z) Example (where A = B = C = D = int):

1 Func<int , int , int , int> 2 q = ( x , y , z ) = > x∗x + y∗y + z∗z ; 1 Func<int , Func<int , Func<int , int> > > 2 q1 = x = > ( y = > ( z = > x∗x + y∗y + z∗z ) ) ; 1 q1 (10)(20) = z = > 500 + z ; 2 // potentially faster than 10*10 + 20*20 + z*z

41 / 53

slide-70
SLIDE 70

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

slide-71
SLIDE 71

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

slide-72
SLIDE 72

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

slide-73
SLIDE 73

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

slide-74
SLIDE 74

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

slide-75
SLIDE 75

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 instance

notation, where its first parameter appears as its target A static class is equivalent to a sealed class with a private constructor: therefore, you can’t subclass it and you can’t instantiate it! Its only purpose is to define extension methods.

44 / 53

slide-76
SLIDE 76

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 instance

notation, where its first parameter appears as its target A static class is equivalent to a sealed class with a private constructor: therefore, you can’t subclass it and you can’t instantiate it! Its only purpose is to define extension methods.

44 / 53

slide-77
SLIDE 77

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 instance

notation, where its first parameter appears as its target A static class is equivalent to a sealed class with a private constructor: therefore, you can’t subclass it and you can’t instantiate it! Its only purpose is to define extension methods.

44 / 53

slide-78
SLIDE 78

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 instance

notation, where its first parameter appears as its target A static class is equivalent to a sealed class with a private constructor: therefore, you can’t subclass it and you can’t instantiate it! Its only purpose is to define extension methods.

44 / 53

slide-79
SLIDE 79

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 instance

notation, where its first parameter appears as its target A static class is equivalent to a sealed class with a private constructor: therefore, you can’t subclass it and you can’t instantiate it! Its only purpose is to define extension methods.

44 / 53

slide-80
SLIDE 80

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) System class string with a new method bool Foo(int).

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

We cannot really extend class string, because it is sealed (which corresponds to final in Java)... However, we can “emulate” such an extension as a static method in a static class:

1 static class MyExtensions { 2 static bool Foo (this string s , int i ) { 3 . . . 4 } 5 }

45 / 53

slide-81
SLIDE 81

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) System class string with a new method bool Foo(int).

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

We cannot really extend class string, because it is sealed (which corresponds to final in Java)... However, we can “emulate” such an extension as a static method in a static class:

1 static class MyExtensions { 2 static bool Foo (this string s , int i ) { 3 . . . 4 } 5 }

45 / 53

slide-82
SLIDE 82

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) System class string with a new method bool Foo(int).

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

We cannot really extend class string, because it is sealed (which corresponds to final in Java)... However, we can “emulate” such an extension as a static method in a static class:

1 static class MyExtensions { 2 static bool Foo (this string s , int i ) { 3 . . . 4 } 5 }

45 / 53

slide-83
SLIDE 83

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 instance method for a string object!

1 string s = ”abc” ; 2 3 var b1 = MyExtensions . Foo ( s , 7 ) ; // static call 4 5 var b2 = s . Foo ( 7 ) ; // ”instance”-like call

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

46 / 53

slide-84
SLIDE 84

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 instance method for a string object!

1 string s = ”abc” ; 2 3 var b1 = MyExtensions . Foo ( s , 7 ) ; // static call 4 5 var b2 = s . Foo ( 7 ) ; // ”instance”-like call

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

46 / 53

slide-85
SLIDE 85

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 a fluent method chaining, i.e. cascading transformations (which leads to crisp expressions) – similar to Unix-like pipelines For example, besides Foo, assume a couple of other similar methods, Goo and Hoo. Contrast the following two equivalent calls, comparing them for expressiveness:

1 var b1 = 2 MyExtensions . Hoo( 3 MyExtensions . Goo( 4 MyExtensions . Foo ( s , 1) , 2) , 3 ) ; 5 6 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

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

47 / 53

slide-86
SLIDE 86

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 a fluent method chaining, i.e. cascading transformations (which leads to crisp expressions) – similar to Unix-like pipelines For example, besides Foo, assume a couple of other similar methods, Goo and Hoo. Contrast the following two equivalent calls, comparing them for expressiveness:

1 var b1 = 2 MyExtensions . Hoo( 3 MyExtensions . Goo( 4 MyExtensions . Foo ( s , 1) , 2) , 3 ) ; 5 6 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

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

47 / 53

slide-87
SLIDE 87

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 a fluent method chaining, i.e. cascading transformations (which leads to crisp expressions) – similar to Unix-like pipelines For example, besides Foo, assume a couple of other similar methods, Goo and Hoo. Contrast the following two equivalent calls, comparing them for expressiveness:

1 var b1 = 2 MyExtensions . Hoo( 3 MyExtensions . Goo( 4 MyExtensions . Foo ( s , 1) , 2) , 3 ) ; 5 6 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

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

47 / 53

slide-88
SLIDE 88

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 real instance methods:

  • Cannot access private members
  • Cannot be polymorphically overridden

48 / 53

slide-89
SLIDE 89

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

slide-90
SLIDE 90

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 : int ) = 2 i f (n <= 0) then 1 3 else (n ∗ f a c t (n−1))

Tail recursive factorial in F#:

1 l e t rec f a c t t a i l r e c (n : int , acc : int ) = 2 i f (n <= 0) then acc 3 else f a c t t a i l r e c (n−1, n∗ acc )

50 / 53

slide-91
SLIDE 91

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 : int ) = 2 i f (n <= 0) then 1 3 else (n ∗ f a c t (n−1))

Tail recursive factorial in F#:

1 l e t rec f a c t t a i l r e c (n : int , acc : int ) = 2 i f (n <= 0) then acc 3 else f a c t t a i l r e c (n−1, n∗ acc )

50 / 53

slide-92
SLIDE 92

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 : int ) = 2 i f (n <= 0) then acc 3 else f a c t t a i l r e c (n−1, n∗ acc )

Tail recursive factorial in F# – reverse engineered in C#:

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

51 / 53

slide-93
SLIDE 93

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 : int ) = 2 i f (n <= 0) then acc 3 else f a c t t a i l r e c (n−1, n∗ acc )

Tail recursive factorial in F# – reverse engineered in C#:

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

51 / 53

slide-94
SLIDE 94

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 use

memoization or other optimisations)

1 // combinatorial explosion 2 int Fib ( int n) { 3 i f (n <= 1) return 1; 4 return f i b (n−1) + f i b (n−2); 5 }

  • Inefficient implementations in non-FP languages, via actual

calls (even potential stack overflow)

52 / 53

slide-95
SLIDE 95

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 or
  • ther optimisations)
  • To use immutable values only (avoid changing the values of

variables)

  • Efficient implementation of tail calls, which are automatically

transformed into loops

53 / 53