// moved 2 units farther from the origin, and translated 1 unit to the
// right and 3 units down
This example is very basic for a graphics transformation, but hopefully it gives you a
glimpse into the power of storing functions in an array. Note the syntax as we apply
each function in the pipeline:
pipeline[i]
accesses element
i
of the pipeline, which
evaluates to a function. Then the function is invoked (parentheses). The point is
passed in, and then assigned back to itself. In this way, the point is the cumulative
result of executing each step in the pipeline.
Pipeline processing is not just found in graphics applications: it’s also popular in
audio processing and many scientific and engineering applications. In reality, any
time you have a series of functions you need to execute in a specified order, a pipeline
is a useful abstraction.
Pass a Function into a Function
We’ve already seen some examples of passing functions to functions: we have passed
functions to
setTimeout
or
forEach
. Another reason to pass a function to a function
is to manage asynchronous programming, a paradigm that’s exploded as asynchro‐
nous programming has become more popular. A common way to achieve asynchro‐
nous execution is to pass a function (usually called a callback, and often abbreviated
cb) into another function. This function is invoked (called) when the enclosing func‐
tion is done with whatever it’s doing. We will be discussing callbacks extensively in
Callbacks aren’t the only reason you might want to pass a function into another func‐
tion; it’s also a great way to “inject” functionality. Let’s consider a function called
sum
that simply sums all of the numbers in an array (for the sake of simplicity, we won’t
do any checking or error handling if the array contains elements other than num‐
bers). This is an easy enough exercise, but what if we then need a function that
returns the sum of squares? We could, of course, simply write a new function called
sumOfSquares
…but what happens when we need the sum of cubes? This is where the
ability to pass a function can be very helpful. Consider this implementation of
sum
:
function
sum
(
arr
,
f
) {
// if no function is supplied, use a "null function" that
// simply returns its argument unmodified
if
(
typeof
f
!=
'function'
)
f
=
x
=>
x
;
return
arr
.
reduce
((
a
,
x
)
=>
a
+=
f
(
x
),
0
);
}
sum
([
1
,
2
,
3
]);
// returns 6
sum
([
1
,
2
,
3
],
x
=>
x
*
x
);
// returns 14
sum
([
1
,
2
,
3
],
x
=>
Math
.
pow
(
x
,
3
));
// returns 36
194 | Chapter 13: Functions and the Power of Abstract Thinking