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 other 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) (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)))
;; live-dillos : list[dillo] -> list[dillo] ;; extracts all the non-dead dillos from the list (define (live-dillos alod) (filter (lambda (adillo) (not (dillo-dead? adillo))) alod))
;; tigers-selling : string list[tiger] -> list[tiger] ;; extracts names of all tigers that sell the named item (define (tigers-selling item alot) (map tiger-name (filter (lambda (atiger) (string=? item (tiger-sells atiger))) alot)))
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.
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) (string=? item (tiger-sells atiger))) ;; tigers-selling : string 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) (string=? item (tiger-sells atiger))) ;; tigers-selling : string 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 : string list[tiger] -> list[tiger] ;; extracts all tigers that sell the named item (define (tigers-selling item alot) (local ((define (tiger-sells-item atiger) (string=? item (tiger-sells atiger)))) (filter tiger-sells-item? alot)))
This page maintained by Kathi Fisler Department of Computer Science Worcester Polytechnic Institute |