Here are some examples of functions written using filter:
;; dead-dillos : list[dillo] -> list[dillo] ;; extract all the dead dillos from the given list of dillos (define (dead-dillos alod) (filter dillo-dead? alod))
This one has several reasonable implementations
;; dead-dillos2 : list[animal] -> list[dillo] ;; extract all the dead dillos from the given list of animals (define (dead-dillos2 aloa) (filter dillo-and-dead? alod)) (define (dillo-and-dead? an-ani) (and (dillo? an-ani) (dillo-dead? an-ani))) ---------------------------------------------------- (define (dead-dillos2 aloa) (local [(define (dillo-and-dead? an-ani) (and (dillo? an-ani) (dillo-dead? an-ani)))] (filter dillo-and-dead? aloa))) ---------------------------------------------------- (define (dead-dillos2 aloa) (filter (lambda (an-ani) (and (dillo? an-ani) (dillo-dead? an-ani))) aloa)) ---------------------------------------------------- (define (dead-dillos2 aloa) (filter dillo-dead? (filter dillo? aloa))) ---------------------------------------------------- (define (dead-dillos2 aloa) (dead-dillos (filter dillo? aloa)))
;; tigers-selling : symbol list[tiger] -> list[tiger] ;; extracts all tigers that sell the named item (define (tigers-selling item alot) (local [(define (sells? atiger) (symbol=? item (tiger-sells atiger)))] (filter sells? alot)))
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.
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 |