Functional Programming First Class Functions, Lambdas and Closures

Functional Programming First Class Functions, Lambdas and Closures

Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Functional Programming First class functions, lambdas and closures Radu Nicolescu Department of Computer Science University of Auckland 23 July 2018 1 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java 1 Programming paradigms 2 Pure FP 3 Recursion 4 C# Delegates 5 Lambda expressions 6 Closures 7 More Lambdas 8 Quiz { Simple scenarios 9 Lambdas in Javascript 10 Lambdas in Java 2 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Programming paradigms • Object-oriented: develop complex objects starting with simple objects (using inheritance, aggregation, delegation, ...) • Functional: develop complex functions starting with simple functions (using function composition, Kleisli, ...) • Object-oriented or functional? • Object-oriented and functional! More dimensions, more tools! • Most modern languages evolve towards a multi-paradigm style • Object-first: C#, Java, C++, ... • Functional-first: F#, Javascript (Lisp in Java syntax), ... • Object-functional: Scala, ... 4 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Side-bar: functions and methods • In classical OOP, functions only appear as methods: • Static/class methods • Instance methods (cf. this pointer) • Other languages, including FP, have standalone, even top-level, functions • Problem: how to represent anonymous inline functions (such as lambdas) in OOP? • Solution: embed these in the current object, if possible, or inside hidden automatically constructed objects { more at closures 5 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Basic ingredients of FP • first-class and higher order functions (aka, functionals) • informally, you can work with functions as with any other objects { and compose them! • you can have functions that take functions as parameters and return functions (functions which may be dynamically composed) • currying or partial application of functions • memoization (or caching) of function results • no side effects and immutable values (next slide) 6 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Pure FP • Function results should only depend on parameter values • No side effects: Functions should not change the global state or any persistent state (unlike object methods which change the object's state) • Immutable values: Ideally, functions should not change any value at all! { This is possible if we use recursion instead of classical loops... • As one of the advantages, programs will be easier to prove correct, to optimize or to parallelize 8 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Pure FP • For example, if f and g don't change any global variable nor any of their parameters (i.e., a; b; c; d), the following two statements can run in parallel, on a dual-core machine: 1 x=f(a,b); | function f could be evaluated on core #1 2 3 y=g(c,d); | function g could be evaluated on core #2 • However, many practical languages, including C# (and F#), do accept side effects, although some of them will try to explicit or localize these (e.g., via so-called monads) 9 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Variables and mutability in C# • Class fields and properties : vast topic, but not much of our concern here... • var or normal declarations are mutable 1 var x=10; x=x+1; 2 i n t x=10; x=x+1; • const defines compile-time immutable values 1 const x = 1 0 ; • readonly defines run-time immutable fields { maybe differently initialised in constructors, but then is frozen 1 readonly int x ; 10 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Variables and mutability in C# • Shallow vs deep immutability • Shallow immutable complex objects such as arrays 1 c l a s s C f 2 public static readonly int []A 3 = new i n t [] f 10 , 20 , 30 , g ; 4 g 5 6 void Main ( ) f 7 var B = new i n t [] f 100, 200, 300, g ; 8 // C .A = B; // NOT allowed 9 C .A [ 1 ] = 200; // allowed! 10 C .A. Dump ( ) ; 11 g • Conclusions: flexible but porous 11 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Variables and mutability in F# • Class fields and properties : vast topic, but not much of our concern here... • let declarations are immutable { not \variables" but values 1 l e t x = 10 • x = x + 1 is legal (!) but does NOT mean what one would think: it is a boolean equality test that returns false ! • Mutable variables must be explicitly declared so 1 l e t mutable x = 10 2 x <− x + 1 • Increased awareness: the assignment to a mutable variable uses a distinct op sign <− 12 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Variables and mutability in F# • Still shallow immutable arrays (but not other objects) 1 l e t A = [ j 1 0 ; 2 0 ; 3 0 ; j ] // A itself is immutable 2 A . [ 1 ] <− 200 // allowed! 3 A. Dump ( ) • Why this exception for arrays? Because of the HUGE body of scientific algorithms, which have been developed and optimised for FORTRAN mutable arrays • F# encourages a more pure style, and promotes increased awareness of mutability { but still allows one the choice to use other styles 13 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Variables and mutability in JS • var declarations are mutable with global scope or function \global" scope 1 var x = 10 • let declarations are mutable with block local scope 1 i f ( b ) f 2 l e t x = 10 3 x = x + 1 4 g • const declarations are immutable with block local scope 1 i f ( b ) f 2 const x = 10 3 // x = x + 1 // not allowed 4 g • More in part (M) 14 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Imperative factorial • F# 1 l e t f a c t n : i n t = 2 l e t mutable m = n 3 l e t mutable f = 1 4 while (m >= 1) do 5 f <− f ∗ m 6 m <− m − 1 7 f 8 9 p r i n t f n "Imperative: %A" (fact 5) 16 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Naive recursive factorial • F# 1 l e t rec f a c t ' n = 2 i f n <= 0 then 1 3 e l s e ( f a c t ' ( n−1)) ∗ n 4 5 p r i n t f n "Naive Recursive: %A" (fact ' 5) • Performance issues, stack overflow 17 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Tail recursive factorial • F# 1 l e t f a c t ' ' n = 2 l e t rec f a c t tailrec n acc = 3 i f ( n <= 0) then acc 4 e l s e f a c t t a i l r e c ( n−1) ( n∗ acc ) 5 f a c t t a i l r e c n 1 6 7 p r i n t f n "Tail Recursive: %A" (fact '' 5) • F# : TCO = Tail Call Optimisation • NO performance issues, NO stack overflow 18 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Tail recursive factorial { reverse engineered • C# : recursion ) while loop! 1 s t a t i c i n t f a c t t a i l r e c ( i n t n , i n t acc ) f 2 while ( n > 0) f 3 acc = n ∗ acc ; 4 n = n − 1 ; 5 g 6 return acc ; 7 g 8 public static int f a c t ( i n t n ) f 9 return f a c t tailrec(n, 1); 10 g • NO performance issues, NO stack overflow 19 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java C# Delegates in a nutshell • Consider this scenario 1 c l a s s C f 2 p u b l i c i n t F( i n t x ) f return x +1; g 3 p u b l i c i n t G( i n t y ) f return y+y ; g 4 public static int H( i n t z ) f return z ∗ z ; g 5 g • What do these three methods have in common? • Their signature: int!int • Usage (assuming using static System.Console) 1 WriteLine ($"f c1 . F (3)g f c2 .G(3)g fC .H(3)g "); 2 // 4 6 9 21 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java C# Delegates in a nutshell • Same scenario 1 c l a s s C f 2 p u b l i c i n t F( i n t x ) f return x +1; g 3 p u b l i c i n t G( i n t y ) f return y+y ; g 4 public static int H( i n t z ) f return z ∗ z ; g 5 g • More flexible usage using typed function pointers! 1 Func <int , int > f = c1 . F ; 2 Func <int , int > g = c2 .G; 3 Func <int , int > h = C .H; 4 WriteLine ($"f f (3)g fg (3)g fh (3)g "); 5 // 4 6 9 • The same pointer, e.g. f, could point in turn to all these methods! 22 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java C# Delegates • A delegate is a .NET type-safe pointer to a function, i.e. to a class or instance method • To call an instance method: obj.F (...) • To call a static method: Class .H (...) • Technically, a delegate is an object with two properties • Method: a pointer to the instance or class method (F,H) • Target { for instance methods: pointer to actual object (obj) • instance method calls depend on the actual target object • Target { for static methods: null (usually) • static methods can be fully resolved by the compiler (so the actual class is not needed at runtime) 23 / 61 Paradigms Pure Rec Delegates Lambdas Closures More QuizJS Java Predefined delegate types in C# { Function types in F# 1 Func<T1,T2,..

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    51 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us