Higher Order Functions
Abstractions
Abstraction is:
- the process of hiding away necessary, but immaterial details
- … to allow for a programmer to work more closely with the problem that is actually being solved
For example:
- we abstract away the underlying machine when we use high-level programming languages, like JavaScript and Python
- whereas low-level languages are tied closely to the architecture and organization of the machine that you're working on
Abstraction Continued
What are some constructs for abstraction in Java?
- Classes (there's even a keyword, abstract… what does that do?)
- Interfaces
- Methods / Functions
Higher Order Functions as Constructs for Abstractions
A higher order function is a function that does at least one of the following:
- takes a function or functions as a parameter (input)
- returns a function
You Might Know These Higher Order Functions From…
In languages where functions are first class citizens it's common to have some implementation of the following higher order functions that work with arrays:
- foreach - calls a function for every element in an array (no return value)
- map - calls a function on every element in an array to return a new array composed of those elements
- filter - creates and returns a new array composed of only elements that pass a supplied test function
- reduce - reduces an array to a single value, and returns that value
Our Implementation of forEach
Create a function called forEach
. →
- it'll take two parameters, the array,
arr
, and some sort of function,action
- it will run the function for every element in the array
var numbers = [1, 2, 3];
function forEach(arr, action) {
for (var i = 0; i < arr.length; i++) {
action(arr[i]);
}
}
// instead of just logging each number as is, log the square of ever number
forEach(numbers, function(arrayElement) { console.log(arrayElement * arrayElement)});
A Few Other Notes on Both Implementations
- all variables are declared at the top of the function (why? →) …to avoid ambiguities when a variable declaration is hoisted
- the formatting of the variable declarations is one per line, indented… in a single statement
- indentation for both nested
for
loops and nestedforEach
calls greatly helps readability - either function works fine!
- forEach - more expressive / reads more naturally, less complexity
- for - slightly faster
Filtering an Array
Create a function called filter that filters an array by: →
- taking an array as one argument and a function, a test, as the other
- it should return an entirely new array populated with only the elements that pass the test
- test by using it to keep only the odd numbers in an array of numbers
function filter(arr, test) {
var filtered = [];
arr.forEach(function(element) {
if(test(element)) {
filtered.push(element)
}
});
return filtered;
}
result = filter([1, 2, 3, 4], function(x) {
return x % 2 == 1;
});
console.log(result);
Using Filter!
Again, JavaScript arrays already have a filter method:
- an array method, so only one parameter, a callback function (the test) … no need to pass in the array
- callback is executed with element value, element index and original array object
- callback returns either true or false
- filter returns a new filtered array
Try using it to filter our deck of cards so that we only have cards that have a numeric value that's less than or equal to 3 →
var deck = generateCards();
var filtered = deck.filter(function(card) {
return parseInt(card.face, 10) <= 3;
});
console.log(filtered);