You are on page 1of 45

SWE4205 – STRUCTURED

PROGRAMMING
A. A. Datti
COURSE OUTLINE
1. Introduction to Structured Programming
2. What is functional programming?
3. Functional vs. Object-oriented programming
4. Functions
5. Understanding your application’s control flow
6. Method chaining and Function chaining
7. Reasoning about your code
8. Learning to think recursively
SWE4205 - STRUCTURED PROGRAMMING 2
FUNCTIONS
FUNCTIONS
In functional programming, functions are the basic units of work, which
means everything centers around them.

Functions can return either a computed value or undefined (void function)


back to the caller.

Because FP works a lot like math, functions are meaningful only when they
produce a usable result (not null or undefined); otherwise, the assumption is
that they modify external data and cause side effects to occur.
FUNCTIONS
We can distinguish between expressions (functions that produce a value)
and statements (functions that don’t).

Imperative and procedural programming are mostly made up of ordered


sequences of statements; but FP is entirely expressional, so void
functions don’t serve a purpose in this paradigm

JavaScript functions have two important characteristics that are the bread
and butter of its functional style: they are first-class and higher-order
FUNCTIONS AS FIRST-CLASS
CITIZENS
In JavaScript, the term first-class comes from making functions
actual objects in the language — also called first-class citizens.

You are probably used to seeing functions declared like this:


FUNCTIONS AS FIRST-CLASS
CITIZENS
In FP Languages like JavaScript, a function (similar to an object) can be
assigned to variables as an anonymous function or lambda expression:
FUNCTIONS AS FIRST-CLASS
CITIZENS
Although not common practice, functions can also be instantiated via
constructors, which is proof of their first-class nature in JavaScript.

The constructor takes the set of formal parameters, the function body, and the
new keyword, like so:
HIGHER-ORDER FUNCTIONS
Because functions behave like regular objects, you can intuitively expect that they
can be passed in as function arguments and returned from other functions. These are
called higher-order functions.
The applyOperation function below takes two arguments and applies any operator
function to both of them:
HIGHER-ORDER FUNCTIONS
In the next example, the add function takes an argument and returns a function that, in turn,
receives a second argument and adds them together:

Because functions are first-class and higher-order, JavaScript functions can behave as values,
which implies that a function is nothing more than a yet-to-be-executed value.
HIGHER-ORDER FUNCTIONS
Higher-order functions help you get shorter, more concise, and easier to understand code. The
following are some HOF available in JavaScript:
•reduce() to apply an operation to a whole array, reducing it to a single result
•map() to transform one array into another by applying a function to each of its elements
•flat() to make a single array out of an array of arrays
•forEach() to simplify writing loops by abstracting the necessary looping code
•filter() to pick some elements from an array
•find() and findIndex() to search for elements that satisfy a condition
•every() and some(), to check an array for a Boolean test
REDUCING AN ARRAY TO A
VALUE
It is common to loop through an array, performing an operation to
produce a single value (maybe the sum of all the array values) as a
result.

This kind of operation can usually be implemented functionally by


applying reduce().

reduce() function traverses the array, applying a reducing function to


each element and to the accumulated value:
REDUCING AN ARRAY TO A
VALUE
REDUCING AN ARRAY TO A
VALUE
•All the aspects of loop control are automatically taken care of, so
you don't even have the possibility of, say, an off-by-one mistake.

•The initialization and handling of the result values are also done
implicitly.

•Unless you work really hard at being impure and modifying the
original array, your code will be side effect free.
SUMMING AN ARRAY
Basically, to reduce an array, you must provide a dyadic function (a
function with two parameters) and an initial value.

In our case, the function will sum its two arguments.

Initially, the function will be applied to the provided initial value and
the first element of the array. So for us, the initial value we have to
provide is a zero, and the first result will be the first element itself
(plus zero).
SUMMING AN ARRAY
Then, the function will be applied again, this time to the
result of the previous operation, and the second element
of the array, and so the second result will be the sum of
the first two elements of the array.

Progressing in this fashion along the whole array, the final


result will be the sum of all its elements
SUMMING AN ARRAY

Instead of having to write out the loop, initializing a variable to hold the result of the
calculations, and going through the array doing the sums, you just declare what
operation should be performed.

This is what is meant by programming declaratively, focusing on what rather than how.
CALCULATING AN AVERAGE
How do you calculate the average of a list of numbers?

If you were explaining this to someone, your answer would surely be


something like sum all the elements in the list and divide that by the
number of elements.

This, in programming terms, is not a procedural description (you don't


explain how to sum elements, or how to traverse the array), but rather a
declarative one, since you say what to do, not how to do it.
CALCULATING AN AVERAGE

We can transform that description of the calculation into an almost


self-explanatory function:
APPLYING AN OPERATION –
MAP
Writing loops that systematically go through all the elements of an
array or collection, starting at the first and looping until finishing
with the last, and performing some kind of process on each of
them is a basic coding exercise, usually learned in the first days of
all programming courses.

We already saw one such kind of operation in the previous section


with reduce(); let’s now turn to a new one, called map().
APPLYING AN OPERATION –
MAP
In mathematics, a map is a transformation of elements from a domain
into elements of a codomain.

For example, you might transform numbers into strings, strings into
numbers , or maybe numbers to numbers:

The important point is that you have a way to transform an element of


the first kind or domain into an element of the second kind, or
codomain.
APPLYING AN OPERATION –
MAP
In our case, this will mean taking the elements of an array
and applying a function to each of them to produce a new
array.

In more computer-like terms, the map function transforms


an array of inputs into an array of outputs.
MAP SYNTAX
callbackFn: Function that is called
for every element of arr. Each time
callbackFn executes, the returned
value is added to newArray.

The callbackFn function accepts


the following arguments:
 element: The current element being
processed in the array.
 index (Optional): The index of the
current element being processed in the
array.
MAP - EXAMPLES
MAP VS LOOP
First, you don't have to write any loops, so that's one less possible
source of bugs.

Second, you don't even have to access the original array or the index
position, even though they are there for you to use if you really need
them.

Lastly, a new array is produced, so your code is pure (though, of


course, if you really want to produce side effects, you can).
EXTRACTING DATA FROM
OBJECTS
Suppose that we have some geographic data (as shown in the following snippet)
related to some South American countries and the coordinates (latitude and
longitude) of their capitals.
Let's say that we want to calculate the average position of those cities. How would
we go about it?
EXTRACTING DATA FROM
OBJECTS
We would want to use our average() function (which we developed earlier in
this chapter), but there is a problem: that function can only be applied to an
array of numbers, and what we have here is an array of objects.

We can, however, do a trick: we can focus on calculating the average latitude


(we can deal with the longitude later, in a similar fashion).

We can map each element of the array to just its latitude, and we would then
have an appropriate input for average().
EXTRACTING DATA FROM
OBJECTS

Mapping an array to extract data is powerful, but you must be careful. Let's
now look at a case that seems right, but produces incorrect results!
WORKING WITH RANGES
We want a range(start,stop) function that generates an array of numbers, with
values ranging from start (inclusive) to stop (exclusive):

Why fill(0)? All undefined array elements are skipped by map(), so we need to fill
them with something or our code will have no effect.
WORKING WITH RANGES
We can redo our factorial function by applying range() and then reduce().
The idea of this is to simply generate all the numbers from 1 to n and then multiply
them together:
MORE GENERAL LOOPING
The preceding examples that we've seen simply loop through arrays, doing some
work.

However, sometimes you need to do a loop, but the required process doesn't really
fit map() or reduce().

For instance when you want to perform an action within the loop but not return
anything at the end of the loop.

So what can be done in such cases? There is a forEach() method that can help.
MORE GENERAL LOOPING
If you use the range() function that we defined previously, you can also perform
common loops of the for(i=0; i<10; i++) variety.
We might write yet another version of factorial (!) using that:
LOGICAL HIGHER-ORDER
FUNCTIONS
Up to now, we have been using higher-order functions to produce new results,
but there are also some other functions that produce logical results by
applying a predicate to all the elements of an array

In computer science, it has the meaning of a function that returns true or


false.

Using these functions implies that your code will become shorter: you can,
with a single line of code, get the results corresponding to the whole set of
values.
FILTERING AN ARRAY
A common need that we will encounter is to filter the elements of an array
according to a certain condition.
The filter() method lets you inspect each element of an array in the same
fashion as map().
The difference is that instead of producing a new element, the result of your
function determines whether the input value will be kept in the output (if the
function returned true) or if it will be skipped (if the function returned false).
Also similar to map(), filter() doesn't alter the original array, but rather
returns a new array with the chosen items.
FILTERING AN ARRAY
Always return something from your predicate:

If you forget to include a return, the function will


implicitly return undefined, and since that's a falsy
value, the output will be an empty array.

The copy that is made is shallow: If the input array


elements are objects or arrays, then the original
elements will still be accessible.
FILTER() - EXAMPLE
FIND ALL PRIME NUMBERS IN
AN ARRAY
FILTERING AN ARRAY
Suppose a service has returned a JSON object, which itself has an array of objects
containing an account id and the account balance.
How can we get the list of IDs that are in the red, with a negative balance? The input
data could be as follows:
FILTERING AN ARRAY
We could get the delinquent accounts with something like the following. You can
check that the value of the delinquent variable correctly includes the two IDs of
accounts with a negative balance:

By the way, given that the filtering operation produced yet another array, if you just
wanted the accounts IDs, you could get them by mapping the output to just get the
ID field. And if you didn't care for the intermediate result, a one-liner would have
done as well:
SEARCHING AN ARRAY
Sometimes, instead of filtering all the elements of an array, you want to find
an element that satisfies a given predicate (logical relation).
There are a couple of functions that can be used for this, depending on your
specific needs:
find() searches through the array and returns the value of the first element
that satisfies a given condition, or undefined if no such element is found
findIndex() performs a similar task, but instead of returning an element, it
returns the index of the first element in the array that satisfies the condition,
or -1 if none were found
SEARCHING AN ARRAY
Going back to the geographic data we used earlier, we could easily find a given
country by using the find() method.
For instance, let's get data for Brazil ( "BR"); it just takes a single line of code:
SEARCHING AN ARRAY
If we wanted the position of the country in the array, we would have used
findIndex():
HIGHER-LEVEL PREDICATES –
SOME, EVERY
The last functions we are going to consider greatly simplify going through arrays to
test for conditions:
every(), which is true if and only if every element in the array satisfies a given
predicate
some(), which is true if at least one element in the array satisfies the predicate
For example, we could easily check our hypothesis about all the countries having
negative coordinates:
ASSIGNMENT
You run a company and you just decided to give all your employees a N10,000 raise. Write the program in OOP
style and in Functional style?
In OOP:
Create Employee class that initializes with name and salary, and has a change salary instance method
Create instances of employees
Use each method to change the salary attribute of employees by +10,000
In FP:
Create employees array, which is an array of arrays with name and corresponding salary
Create a change_salary function that returns a copy of a single employee with the salary field updated
Create a change_salaries function that maps through the employee array and delegates the calculation of the new
salary to change_salary
Use both methods to create a new dataset, named ‘happier employees’
END

You might also like