CS 1102: Programming Language Concepts
Notes on Filter and Lambdas 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 operator (lambda ...) passed to filter here refers to item, which isn't a parameter to that function. That's okay, because the lambda 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 Local Functions/Lambdas Necessary?

For dead-dillos2, we have solutions that use lambda and solutions that do not. For tigers-selling, we have only one solution that uses lambda. Let's try to implement tigers-selling without lambda.

We've said that lambdas let us create un-named functions. So, to remove the lambda, we can try to define the function we pass in 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 (i.e. create the lambda) inside the body of tigers-selling. If want to give the function a name use local (note that you still have to nest the definition though). 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