Functional Programming • Functional code is characterised by one thing: the absence of side effects. It doesn’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. Every other “functional” thing can be derived from this property. Any examples of functions with side effects and no side effects? • The key to Functional Programming is in the name: functions. FP is about immutability and composing functions rather than objects.
Functions are first class • What makes something first class?
Functions are first class • What makes something first class? • It can be created on demand • It can be stored in a data structure • It can be passed as an argument to a function • It can be returned as the value of a function
Creating functions on demand using composition Find the fifth element of a collection: (def fifth (comp first rest rest rest rest)) (fifth [1 2 3 4 5]) •comp : Takes a set of functions and returns a fn that is the composition of those fns •first: Returns the first item in the collection •rest: Returns a possibly empty seq of the items after the first. •Find nth element of a collection using composition?
CREATING FUNCTIONS ON DEMAND USING PARTIAL FUNCTIONS ((partial + 5) 100 200) ;=> 305 The function partial builds a new function that partially applies the single argument 5 to the addition function. When the returned partial function is passed the arguments 100 and 200, the result is their summation plus that of the value 5 captured by partial. •
USING FUNCTIONS AS DATA • First-class functions can not only be treated as data; they are data • It can be stored in a container expecting a piece of data, be it a local, a reference, collections, or anything able to store a java.lang.Object. (defn join {:test (fn [] (assert (= (join "," [1 2 3]) "1,3,3")))} [sep s] (apply str (interpose sep s))) •
Higher-order functions A higher-order function is a function that does at least one of the following: • Takes one or more functions as arguments • Returns a function as a result
Functions as Arguments (sort-by second [[:a 7], [:c 13], [:b 21]]) ;;=> ([:a 7] [:c 13] [:b 21])
Functions as return values •(complement f) Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value. (def not-empty? (complement empty?)) ;; #'user/not-empty?
Pure Functions Simply put, pure functions are regular functions that, through convention, conform to the following simple guidelines • The function always returns the same result, given the same arguments. • The function doesn’t cause any observable side effects.
Pure or Impure? var x = 5; function addToX(a) { return a + x; } function getLength(array) { return array.length; } •
Pure or Impure? function add(x, y) { return x + y; } function add(x,y) { updateDatabase(); return x + y; } •
REFERENTIAL TRANSPARENCY TESTABILITY If a function is referentially transparent, then it’s easier to reason about and therefore more straightforward to test. Imagine the confusion should you add further impure functions based on further external transient values. OPTIMIZATION If a function is referentially transparent, then it can more easily be optimized using techniques such as memoization.
OOPS vs FP Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which are data structures that contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods Functional programming is a programming paradigm, a style of building the structure and elements of computer programs, that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data
OOP vs FP  the data (the stuff a program knows) the behaviors (the stuff a program can do to/with that data) •OOP says that bringing together data and its associated behavior in a single location (called an “object”) makes it easier to understand how a program works. •FP says that data and behavior are distinctively different things and should be kept separate for clarity.
Let’s say you run a company and you’ve just decided to give all your employees a $10,000.00 raise. How could we write a command-line script to make this change?
Approach using OOP class Employee def initialize(name, salary) @name = name @salary = salary end def change_salary(amt) @salary = @salary + amt end def description "#{@name} makes #{@salary}" end end •
employees = [ Employee.new("Bob", 100000.0), Employee.new("Jane", 125000.0) ] Each Employee.new(...) call creates an object with data (@name and @salary) and behavior (change_salary and description) employees.each do |emp| emp.change_salary(10000.0) end •
employees.each do |emp| emp.change_salary(10000.0) end We call the “change_salary” method we defined in our class, passing in a value of 10000.0. This adds our $10K to the employee’s salary and stores the sum in @salary, overwriting the existing value The description method to build our output string instead of trying to access the data fields (@salary and @name) directly. This is called “data hiding” and it allows us to change the names of our instance variables without forcing the users of our object to change how they use it.
FP Approach employees = [ [ "Bob", 100000.0 ], [ "Jane", 125000.0 ] ] Instead of converting the data to an object and then calling methods on it, we write a pair of standalone methods called change_salaries (plural) and change_salary (singular)  we write a pair of standalone methods called change_salaries (plural) and change_salary (singular). We pass change_salaries two arguments: the array of arrays representing our data and the change amount. change_salaries uses map instead of the each method we used in the OOP version •
FP Approach happier_employees = change_salaries(employees, 10000.0) Because we don’t have objects, change_salaries requires that we pass in not just the amount, but also the data we want to modify.
FP Approach happier_employees.each do |emp| puts "#{emp[0]} makes #{emp[1]}" end Finally, we use ‘each’ to walk through every record in happier_employees and generate the output message ourselves. This fits the FP model because FP likes to view everything as a data transformation: you start with this dataset, apply these transformations to it (in this case, adding $10K) and generate a new dataset Another subtle -- but important -- difference is that in the OOP version change_salary used each to process each employee, but the FP version uses map. Instead of changing the original value, ’map’ creates a copy of the array containing the return value of each pass. When all elements have been processed, map hands us the copy with all the new values, which we store in happier_employees. The original array is untouched! This idea of not changing the contents (or “state”) of a variable once it’s been created is called immutability and is another key aspect of FP. Before and After state.

Basics of Functional Programming

  • 1.
    Functional Programming • Functional codeis characterised by one thing: the absence of side effects. It doesn’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. Every other “functional” thing can be derived from this property. Any examples of functions with side effects and no side effects? • The key to Functional Programming is in the name: functions. FP is about immutability and composing functions rather than objects.
  • 2.
    Functions are firstclass • What makes something first class?
  • 3.
    Functions are firstclass • What makes something first class? • It can be created on demand • It can be stored in a data structure • It can be passed as an argument to a function • It can be returned as the value of a function
  • 4.
    Creating functions on demandusing composition Find the fifth element of a collection: (def fifth (comp first rest rest rest rest)) (fifth [1 2 3 4 5]) •comp : Takes a set of functions and returns a fn that is the composition of those fns •first: Returns the first item in the collection •rest: Returns a possibly empty seq of the items after the first. •Find nth element of a collection using composition?
  • 5.
    CREATING FUNCTIONS ONDEMAND USING PARTIAL FUNCTIONS ((partial + 5) 100 200) ;=> 305 The function partial builds a new function that partially applies the single argument 5 to the addition function. When the returned partial function is passed the arguments 100 and 200, the result is their summation plus that of the value 5 captured by partial. •
  • 6.
    USING FUNCTIONS ASDATA • First-class functions can not only be treated as data; they are data • It can be stored in a container expecting a piece of data, be it a local, a reference, collections, or anything able to store a java.lang.Object. (defn join {:test (fn [] (assert (= (join "," [1 2 3]) "1,3,3")))} [sep s] (apply str (interpose sep s))) •
  • 7.
    Higher-order functions A higher-orderfunction is a function that does at least one of the following: • Takes one or more functions as arguments • Returns a function as a result
  • 8.
    Functions as Arguments (sort-bysecond [[:a 7], [:c 13], [:b 21]]) ;;=> ([:a 7] [:c 13] [:b 21])
  • 9.
    Functions as returnvalues •(complement f) Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value. (def not-empty? (complement empty?)) ;; #'user/not-empty?
  • 10.
    Pure Functions Simply put,pure functions are regular functions that, through convention, conform to the following simple guidelines • The function always returns the same result, given the same arguments. • The function doesn’t cause any observable side effects.
  • 11.
    Pure or Impure? varx = 5; function addToX(a) { return a + x; } function getLength(array) { return array.length; } •
  • 12.
    Pure or Impure? functionadd(x, y) { return x + y; } function add(x,y) { updateDatabase(); return x + y; } •
  • 13.
    REFERENTIAL TRANSPARENCY TESTABILITY If afunction is referentially transparent, then it’s easier to reason about and therefore more straightforward to test. Imagine the confusion should you add further impure functions based on further external transient values. OPTIMIZATION If a function is referentially transparent, then it can more easily be optimized using techniques such as memoization.
  • 14.
    OOPS vs FP Object-orientedprogramming (OOP) is a programming paradigm based on the concept of "objects", which are data structures that contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods Functional programming is a programming paradigm, a style of building the structure and elements of computer programs, that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data
  • 15.
    OOP vs FP  thedata (the stuff a program knows) the behaviors (the stuff a program can do to/with that data) •OOP says that bringing together data and its associated behavior in a single location (called an “object”) makes it easier to understand how a program works. •FP says that data and behavior are distinctively different things and should be kept separate for clarity.
  • 16.
    Let’s say yourun a company and you’ve just decided to give all your employees a $10,000.00 raise. How could we write a command-line script to make this change?
  • 17.
    Approach using OOP classEmployee def initialize(name, salary) @name = name @salary = salary end def change_salary(amt) @salary = @salary + amt end def description "#{@name} makes #{@salary}" end end •
  • 18.
    employees = [ Employee.new("Bob",100000.0), Employee.new("Jane", 125000.0) ] Each Employee.new(...) call creates an object with data (@name and @salary) and behavior (change_salary and description) employees.each do |emp| emp.change_salary(10000.0) end •
  • 19.
    employees.each do |emp| emp.change_salary(10000.0) end Wecall the “change_salary” method we defined in our class, passing in a value of 10000.0. This adds our $10K to the employee’s salary and stores the sum in @salary, overwriting the existing value The description method to build our output string instead of trying to access the data fields (@salary and @name) directly. This is called “data hiding” and it allows us to change the names of our instance variables without forcing the users of our object to change how they use it.
  • 20.
    FP Approach employees =[ [ "Bob", 100000.0 ], [ "Jane", 125000.0 ] ] Instead of converting the data to an object and then calling methods on it, we write a pair of standalone methods called change_salaries (plural) and change_salary (singular)  we write a pair of standalone methods called change_salaries (plural) and change_salary (singular). We pass change_salaries two arguments: the array of arrays representing our data and the change amount. change_salaries uses map instead of the each method we used in the OOP version •
  • 21.
    FP Approach happier_employees =change_salaries(employees, 10000.0) Because we don’t have objects, change_salaries requires that we pass in not just the amount, but also the data we want to modify.
  • 22.
    FP Approach happier_employees.each do|emp| puts "#{emp[0]} makes #{emp[1]}" end Finally, we use ‘each’ to walk through every record in happier_employees and generate the output message ourselves. This fits the FP model because FP likes to view everything as a data transformation: you start with this dataset, apply these transformations to it (in this case, adding $10K) and generate a new dataset Another subtle -- but important -- difference is that in the OOP version change_salary used each to process each employee, but the FP version uses map. Instead of changing the original value, ’map’ creates a copy of the array containing the return value of each pass. When all elements have been processed, map hands us the copy with all the new values, which we store in happier_employees. The original array is untouched! This idea of not changing the contents (or “state”) of a variable once it’s been created is called immutability and is another key aspect of FP. Before and After state.