map(function, list )
function applies a function to a list of values. If you're thinking: 'hey, that sounds like a for loop
', you're correct. FP eschews using transient variables as counters in favor of constructs like
(see Figure 3
|Figure 3: Map() Function Applies a Function to a List of Values|
In FP, side effects is the term for variables that aren't part of the work a function does but rather are helpers required (in this case) to make the loop work. An obvious benefit of reducing or eliminating side effects is that it reduces the number of lines of code, which means fewer bugs. While having fewer bugs (due to improperly initialized variables, counter variables that are not reset or are shadowed, etc.) is certainly a worthwhile benefit, I'm more focused on the code's conciseness.
David Mertz succinctly expresses the benefits of the FP approach by saying that the line
map(mappableFunction, namelist) represents a single programmatic thought. The intent of the code is to "apply the function across the namelist variable's value"—one thought: do this to that. One line of code corresponds to that one thought. Granted you'll face some setup (e.g., in the method definition, etc.), but the actual call to do the work—the essence of the this code block's intent—is clean and concise.
filter( ) function works in a similar manner to
map( ). The differences lie in what it returns. The
map( ) function returns a list of the same length as the list that is passed as an argument to it. The aptly named
filter( ) function returns only those values from the list that meet the conditions of the function that is applied. In other words, it filters out values from the input list (see Figure 4).
|Figure 4: |
Filter( ) Function Filters Out Values from the Input List
At this point, I hope a light bulb or two are flashing in your mind. You might even be thinking that you could nest these functions inside each other to filter desired variables out of a list and then map a function against this list. This is certainly possible, but I'd caution against overzealous nesting with these constructs. One reason is that when you nest these constructs you can't easily pick out intermediate values, and this could make debugging a headache. More significantly, the most conspicuous benefit of these functions is their clear translation of thought to code. An overabundance of nested functions would greatly reduce your code's readability and maintainability.