Index
Overview


The power of functional programming is in passing functions.

Higher-Order Functions


A higher-order function is a function that receives other functions as arguments (parameters) and/or it returns other functions.

Often a higher-order function is a conventional function (e.g., a method) and the passed function is an abbreviated anonymous function.

Let's walk through at a couple examples.

Example: mapElements


The purpose of the function mapElements is to map (convert) a collection of elements into new elements.

Idea of mapElements
This function allows us to derive a new collection (of our choice).

Let's say we have a collection objects that are of type "Student". What we want is a list of the names of the students. This is where the function mapElements comes in.

Note that this is one "specific" example "using" mapElements. The algorithm for mapElements will be "general" so the input can be a collection of "any" type of elements.
 Array       New Array
Student1  --->   Jong
Student2  --->   Asha
Student3  --->   Chin
Student4  --->   Kofi
Student5  --->   Chee
Writing Human Language Algorithm for mapElements
Here we make an attempt at a human language algorithm for mapElements.
function mapElements(elements, mapFct)
	Let newElements = new dynamic array
	Loop over all elements in "newElements" using loop var "nextElem"
		Let newElem = mapFct(nextElem)
		Add nextElem to newElements
	Return newElements
Writing Psuedocode Algorithm for mapElements
We now write our algorithm as pseudocode.

The key part of this method is where we pass the existing element to the map function and it returns a new element.
/** Returns new collection where mapFct is used
to generate new elements from passed (param) elements */
function mapElements(elements, mapFct) {
	let newElements = Array.newDynamic();
	for (let nextElem of elements) {
		let newElem = mapFct(nextElem);
		newElements.add(newElem);
	}
	return newElements
}
Using mapElements: Squaring and Cubing
Now the fun part, which is passing functions (of our choice) to the higher order function.

  • Function that returns the square of a number
  • Call mapElements and pass function "squareFct"
var nums, squareFct, cubeFct, squares, cubes;
nums = [1, 2, 3, 4];
println("Nums: " + nums);

1
squareFct = (n) => n * n; cubeFct = (n) => n * n * n; squares =
2
mapElements(nums, squareFct); cubes = mapElements(nums, cubeFct); println("Squares: " + squares); println("Cubes: " + cubes); _hiddenSource_ function mapElements(elements, mapFct) { let newElements = Array.newDynamic(); for (let nextElem of elements) { let newElem = mapFct(nextElem); newElements.add(newElem); } return newElements } //Try It var nums, squareFct, cubeFct, squares, cubes; nums = [1, 2, 3, 4]; squareFct = (n) => n * n; squares = mapElements(nums, squareFct); cubeFct = (n) => n * n * n; cubes = mapElements(nums, cubeFct); println("Nums: " + nums); println("Squares: " + squares); println("Cubes: " + cubes);
Using mapElements: Computing Wages
Here we convert a list of hours worked to wages.

  • Function that returns a wage given hours and hourlyRate
  • Call mapElements and pass function "wageFct"
//Try It
let hours, hourlyRate, wages, wageFct;
hours = [10, 20, 5];
//$15/hr
hourlyRate = 15;	//$15/hr
wageFct = (nextHours) => nextHours * hourlyRate;
wages = mapElements(hours, wageFct);
println("Hours: " + hours);
println("Hourly Rate: " + hourlyRate);
println("Wages: " + wages);

_hiddenSource_

function mapElements(elements, mapFct) {
	let newElements = Array.newDynamic();
	for (let nextElem of elements) {
		let newElem = mapFct(nextElem);
		newElements.add(newElem);
	}
	return newElements
}

//Try It
let hoursWorked, hourlyRate, wages, wageFct;
hoursWorked = [10, 20, 5];
//$15/hr
hourlyRate = 15;
wageFct = (hours) => hours * hourlyRate;
wages = mapElements(hoursWorked , wageFct);
println("Hours: " + hoursWorked);
println("Hourly Rate: " + hourlyRate);
println("Wages: " + wages);
Using mapElements: Fahrenheit to Celsius
Assume we have Math.round in our programming context.

Note that we apply two different mappings here -- one basic and one that adds a label.

The Fahrenheit to Celsius temperature conversion is:

c = (f - 32) * (5/9)


//Try It
let temperaturesC, mapFct, temperaturesF, labelFct;
temperaturesF = [-15, 0, 32, 50, 80];
fahrenheightToCelsiusFct = (f) => Math.round((f - 32) * (5/9));
temperaturesC = mapElements(temperaturesF, fahrenheightToCelsiusFct);
println("Temperatures (F): " + temperaturesF);
println("Temperatures (C): " + temperaturesC);
labelFct = (value) => '' + value + ' C';
temperaturesC = mapElements(temperaturesC, labelFct);
println("Temperatures (C) Labeled: " + temperaturesC);

_hiddenSource_

function mapElements(elements, mapFct) {
	let newElements = Array.newDynamic();
	for (let nextElem of elements) {
		let newElem = mapFct(nextElem);
		newElements.add(newElem);
	}
	return newElements
}

//Try It
let temperaturesC, fahrenheightToCelsiusFct, temperaturesF, labelFct;
temperaturesF = [-15, 0, 32, 50, 80];
fahrenheightToCelsiusFct = (f) => Math.round((f - 32) * (5/9));
temperaturesC = mapElements(temperaturesF, fahrenheightToCelsiusFct);
println("Temperatures (F): " + temperaturesF);
println("Temperatures (C): " + temperaturesC);
labelFct = (value) => '' + value + ' C';
temperaturesC = mapElements(temperaturesC, labelFct);
println("Temperatures (C) Labeled: " + temperaturesC);

Example: findFirst


The purpose of the function findFirst is to find the first matching element in a collection using a match function. The index is returned.

Idea of findFirst
Say we are given a collectin of Friend objects.

We can use findFirst to search for name, id, or whatever we like.

It returns the index of the first match, or -1 if no match.
 Array
Friend0 (Jong)
Friend1 (Asha)
Friend2 (Chin)
Friend3 (Kofi)
Friend4  (Chee)
Writing Human Language Algorithm for findFirst
Here we take a shot at an algorithm for findFirst.
function findFirst(elements, matchFct) {
	Let i = 0
	Loop while i < elements.size()
		Let nextElem = elements.get(i)
		If matchFct(nextElem) outputs true
			return i
	return -1
Writing Psuedocode Algorithm for findFirst
We now write our algorithm as pseudocode.

The matchFct is used to detect the first match (beginning the search at the start of the passed collection elements).

The matching index is returned (or -1 if no match).
/** Returns the index of the first match, or -1 if no match */
function findFirst(elements, matchFct) {
	for (let i = 0; i < elements.size(); i++) {
		let nextElem = elements.get(i);
		if (matchFct(nextElem))
			return i;
	}
	return -1;
}
Using findFirst: First Odd Number
  • Create a function that returns true on a match (if a num is odd)
  • Call findFirst passing the function
var nums, matchFct, matchIndex;

nums = [0, 2, 4, 11, 10];
println("Nums: " + nums);

1
matchFct = (nextNum) => nextNum % 2 == 1; matchIndex =
2
findFirst(nums, matchFct); println("Match Index (first odd): " + matchIndex); //expected result: 3 matchFct = (nextNum) => nextNum > 100; matchIndex = findFirst(nums, matchFct); println("Match Index (first num > 100): " + matchIndex); //expected result: -1 _hiddenSource_ /** Returns the index of the first match, or -1 if no match */ function findFirst(elements, matchFct) { for (let i = 0; i < elements.size(); i++) { let nextElem = elements.get(i); if (matchFct(nextElem)) return i; } return -1; } //Try It var nums, matchFct, matchIndex; nums = [0, 2, 4, 11, 10]; println("Nums: " + nums); matchFct = (nextNum) => nextNum % 2 == 1; matchIndex = findFirst(nums, matchFct); println("Match Index (first odd): " + matchIndex); //expected result: 3 matchFct = (nextNum) => nextNum > 100; matchIndex = findFirst(nums, matchFct); println("Match Index (first num > 100): " + matchIndex); //expected result: -1