CS 2135: Programming Language Concepts
Notes on Filter and Functions as Arguments


Review of Filter

Here are some examples of functions written using filter:

A Note on Scoping

In the code for tigers-selling, notice that the sells? function passed to filter here refers to item, which isn't a parameter to sells?. That's okay, because sells? is defined inside another function that has item as a parameter.

The collection of code where an identifier is defined is called the scope of that identifier. In Scheme, function parameters are visible anywhere within the body of the function, even within nested functions, objects, structures, etc. The identifier item is therefore active anywhere it appears until the closing paren of the define construct.

When are Nested Functions Necessary?

For dead-dillos2, we have solutions that use local (nested) functions and solutions that do not. For tigers-selling, we have only one solution that uses a nested function definition. Let's try to implement tigers-selling without the nested function.

To do this, we want to define the function outside of tigers-selling:

;; tiger-sells-item? : tiger -> boolean
;; determines whether tiger sells item
(define (tiger-sells-item? atiger)
  (symbol=? item (tiger-sells atiger)))

;; tigers-selling : symbol list[tiger] -> list[tiger]
;; extracts all tigers that sell the named item
(define (tigers-selling item alot)
  (filter tiger-sells-item? alot))

Try running this code. What happens?

You get an "unknown identifier" error on item in tiger-sells-item?. Notice that item is not a parameter to tiger-sells-item?, so Scheme can't find a value for it.

Let's try adding item as a parameter to tiger-sells-item?:

;; tiger-sells-item? : tiger -> boolean
;; determines whether tiger sells item
(define (tiger-sells-item? item atiger)
  (symbol=? item (tiger-sells atiger)))

;; tigers-selling : symbol list[tiger] -> list[tiger]
;; extracts all tigers that sell the named item
(define (tigers-selling item alot)
  (filter tiger-sells-item? alot))

Try running this code. What happens?

Now you get an error that filter expects an operator that takes one argument, but you've given an operator that takes two arguments. By definition, the function you pass to filter may accept only one argument! This version does not work.

In other words, since the filter depends on an argument to tigers-selling, you have to define the filter function inside the body of tigers-selling. Here's the code written with local:

;; tigers-selling : symbol list[tiger] -> list[tiger]
;; extracts all tigers that sell the named item
(define (tigers-selling item alot)
  (local [(define (tiger-sells-item? atiger) (symbol=? item (tiger-sells atiger)))]
    (filter tiger-sells-item? alot)))

This page maintained by Kathi Fisler
Department of Computer Science Worcester Polytechnic Institute