## Select Your Weapon

In this post we’ll continue the refactoring of our less-than-elegant Scheme code for doing reports in our hypothetical Gift Card scenario. We will discover another fundamental building block in the functional programming world, a function that takes a list, and converts each element into a new form using an user provided conversion function.

Together with the list filtering function developed in the previous post in this series, and a simple list-of-numbers summer, we’ll see how our more generic functions can help rewrite a couple of twenty-line problem-specific functions into one-liners, showing off the composability of functions, and hopefully help you increase your understanding of functional programming at the same time.

#### Refactoring continued

In our previous post, we saw that in Scheme (or any functional programming language) using a function as a parameter to another function can be very useful, and helps separating generic behavior from the specifics needed for a particular situation. We implemented a generic list filtering method we called **where**, that let the user provide the filtering rules used by passing in a function that decides which elements to include, and which to exclude.

As you now have the useful **where** function, you can now redefine the **sum-issued-here **function (also introduced in the previous post) as a slightly more generic amount-summer-function plus the where-function to find the gift cards to sum. The amount-summer can be defined like this:

1 ; sum the amounts of all gift card in the list 2 (define (sum-amount giftcards) 3 ; define a helper function to recursively iterate over the list, 4 ; building up the result in an accumulator 5 (define (sum-amount-iterator remaining-giftcards accumulated-sum) 6 ; if there are no more gift cards, return the accumulated sum 7 (if (empty? remaining-giftcards) 8 accumulated-sum 9 ; otherwise, process the current gift card 10 (let* ([current-gc (first remaining-giftcards)] 11 [still-remaining-gcs (rest remaining-giftcards)] 12 ; get the amount from the gift card, and update the sum 13 [new-sum (+ accumulated-sum (amount current-gc))]) 14 ; and recurse on the remaining items 15 (sum-amount-iterator still-remaining-gcs new-sum)))) 16 17 ; call the helper function with initial values 18 (sum-amount-iterator giftcards 0))

It’s very much like several of the other functions you’ve written (and please see the previous post for a thorough explanation of the recursive iteration helper function). The difference from the original implementation is the fact that this function sums *all* provided gift cards, as you can now use a separate function to decide which gift cards to sum, which have greatly improved the composability of our functions. By composability I mean that we can compose (combine) them in several different ways to get different results.

We can now rewrite **sum-issued-here** simply as:

```
(define (sum-issued-here giftcards)
(sum-amount (where issued-here? giftcards)))
```

using the one-line function **issued-here? **we defined in the previous post, to find us the relevant cards to sum. Now the sum-issued-here cannot become much simpler, but the **oldest-used-here** function (defined in the previous post, but basically finds the oldest gift card (the one with the earliest issue-date) used in a particular shop) is still in need of a rewrite. While we can use the **where** function to do part of the job, we cannot re-use much else. We’d rather not write yet-another similar function.

#### Further ideas for refactorings

You have a gut feeling that there’s more generic functionality waiting to get extracted, that would let you rewrite many of your previous functions. Thinking hard about this, considering the definition of the **sum-amount** and the **oldest-used-here **functions, combined with your new-found insight that it’s possible to *parameterize a function with a different function* (something we just put to excellent use in our **where** function), you come up with a few different options for further refactorings:

- Write a more generic summer, where the property to be summed is controlled by a user-supplied function, for example; (
**sum-by**amount giftcards) - Write a generic list converter, where the conversion is controlled by a user-supplied function, so that you could convert a list of gift cards into a list of issue-dates, or amounts.
- Write a generic summer of a list of numbers, that could then be used to sum those amounts
- Along the same lines, you’d need a date-minimizer, to find the earliest date among a list of issue-dates

After a short session of guru meditation, you decide a generic list converter function would be a most beautiful and useful companion to your generic list filtering function, as well as being more composable than **sum-by**, and thus you start with that one. You decide to name it the **select** function.

#### Select - A generic list converter function

Your implementation of the select function turns out much like many other functions in this series, based on the same recursive decomposition of the problem, first work in the current item, and then recurse on the rest of the items.

1 ; the 'select' function converts each item in a list into a new form. 2 ; the conversion is done by the user-supplied convert function! 3 (define (select convert list-of-items) 4 ; our well-known helper 5 (define (select-iterator remaining-items results) 6 (if (empty? remaining-items) 7 (reverse results) ; restore original ordering 8 (let* ([current-item (first remaining-items)] 9 [still-remaining (rest remaining-items)] 10 ; let the passed-in function convert each item into 11 ; a new form and preprend it to the accumulated results 12 [new-results (cons (convert current-item) results)]) 13 ; and recurse on the remaining items 14 (select-iterator still-remaining new-results)))) 15 16 ; call the helper function with initial values 17 (select-iterator list-of-items empty))

This is an immensely useful function. It may appear just like many other, but you’ll use it time and time again when using functional programming techniques. I’d say it’s one of the most fundamental building blocks of functional code. You’ll use it to convert lists of item-IDs to item objects, using a database lookup function, or to convert from items to XML that you’ll write to a file, and many other things.

With this masterpiece done, do you pat yourself on the back? Do you take a well deserved nap? No, there’s no stopping you now, and you proceed relentlessly even though your eyes burn from lack of sleep, by re-writing **sum-amount** (defined at the top of this post) into a generic summer of a list of numbers.

After briefly considering the name ‘reginald’, you rename it **sum**. It really only needs a trivial change on line 13, to replace the call to the amount function with the current list element itself (and perhaps a few identifiers could use more generic names, as the **sum **function is no longer gift-card specific). You decide to spare the readers the sight of the actual implementation.

The revised implementation of **sum-issued-here** is more interesting:

```
(define (sum-issued-here giftcards)
(sum (select amount (where issued-here? giftcards))))
```

This is quite beautiful! Using a few generic and very composable functions and your initial 20-line function has become a one-liner (ok, it’s a *two*-liner, but the line break is for *readability*, OK?) with the aid of a few helpers such as **amount** and **issued-here? – **also one-liners.

#### Step by step

The way this version of **sum-issued-here** works is that if it is called with a list of gift cards, we’ll call them gc1, gc2 and gc3, it will return the sum of the amounts of those issued in a particular shop nearby (as per our definition in the previous post).

- The list of gift cards is passed on to the
**where**function that returns a new list, including only those gift cards for which the**issued-here?**function returns true. Let’s say that was true for gc1 and gc3, but not gc2. - This list with gc1 and gc3 is then passed to the
**select**function, that calls the**amount**function on each gift card, to extract their amounts into a new list that it returns. This list of amounts (well, plain numbers really) now contains say 250, and 175. - This list of numbers is passed on to the
**sum**function that sums it up into the number 425, which then becomes the return value of this particular call to**sum-issued-here.**

In the next post, we’ll try to finalize this refactoring session after discovering yet another useful function, so that we can move on to solve a larger and more challenging problem.

## Leave a comment