You’ll find the companion GitHub repository for Part 2 here. The following post is meant to serve as a foundation for working through the practice problems. You may also want to have a console open to experiment with while reading. Have fun!
Let’s say we want to write a function,
Breaking Down The Logic
Let’s break down the logic of
onlyIntegers, so we understand how it differs from
- Visit each item in an array
- Check if it’s an integer
- Return a result (a new array)
Again, we already know how to do a lot!
Visit each item in an array Check if it’s an integer
- Return a result (a new array)
Traversing the Array
In the last section, we learned how to traverse arrays. We can write a good amount of our
onlyIntegers function knowing only that. First, we’ll define our function and pass it the array
[1,2,"not me", 3, "or me", 4, true, 4.9, 5] as an argument.
tail as before.
We also know that we can traverse the array by recurring with
We know we have to find a terminating condition, which again, is that we’ve checked every item in the array and now it’s empty.
If we run the function as it stands, we successfully visit each element of the array, and then return. But what value should we return?
Returning an Empty Array
Our problem asks us to return a new array. There are many good reasons why we may be asked this. One is that we don’t mutate the original array. Another is that it may make our code more composable. However, we’re not too concerned with such lofty things at the moment. Let’s be lazy and start by just returning an empty array.
If we run
onlyIntegers now, we get exactly what we expect, an empty array. As it stands, we have a function that will traverse an array and return an empty array every time. Well, we are returning an array, so we’re part way there. However, we want it to include only the integer values of the original array.
We want to be able to add values to the array we’re currently returning empty. For that, we’re going to use
Let’s imagine that our function has checked every value in the array and has now been told to return
. The last value it checked was
5, so let’s concat
 with an empty array.
[ 5 ]
Let’s imagine that
[ 5 ] was returned to the function that called it. How do we add that function’s
head value to our array? It’s
4.9. Let’s concat that value as well.
[ 4.9 ].concat() returns
[ 4.9, 5 ]
Next, what was the value of head in the previous function call?
true Have we returned from every function call we’ve made yet? No. We’ve only returned from our very last two function calls. Let’s concat this function call’s
head value when we return as well.
[true].concat([ 4.9, 5 ]) returns
[ true, 4.9, 5 ]
In this way, we build a new array, value by value, as we return from every preceding function call. Only when the very first function call returns do we return from
onlyIntegers entirely, and with a new array in hand. Let’s try that.
Great! Now we return an array with values in it. We’ve achieved our goal of successfully adding values to our new array. The only thing is, we add every single value of the original array to our new array. We still have some work to do.
head as we did before do to some work in the function. What do we want to do? Let’s only add
head to the new array if it’s an integer.
Now we’re done! Let’s follow our logic.
- If the array is empty, simply return an empty array
- If the value is an integer, add
headto the new array
[head].concatand keep checking the rest of the array
- If the value is not an integer, just keep checking the rest of the array
We generally use head when we want to do some work, like checking if a value is an integer. We generally recur when we want to keep checking the rest of the array.