I want to solve a problem in Scheme (R5RS). Here’s my sample data:
(define zipcodes '(
(96774 ookala hawaii)
(90001 losangeles california)
(90263 malibu california)
(10044 newyork newyork)
))
Each list element has the form (ZIP CITY STATE). I want to create a function that works like this: pass STATE as an input, and the function returns the zipcodes of this state (returns an empty list if there is no element for this state).
>(findzips 'california)
(90001 900263)
>(findzips 'berlin)
empty
I try to this by code below but it only return first value not a list
(define (findzips x)
(find x zipcodes))
(define find
(lambda (x zipcodes)
(if (EQ? x (caddr (car zipcodes)))
(list (car (car zipcodes)))
(find x (cdr zipcodes)))))
I’m not allowed to use ! functions or let.
First, there’s a typo in the code you posted:
find3should befind.Let’s look at that function with proper indentation:
If the current entry matches, you don’t try to look for any subsequent match. So the list you return will never contain more than one element.
You always need to look for subsequent elements, i.e. you always need to call
(find x (cdr zipcodes)). A good way would be to calllet, but your homework assignment rules that out. You can just duplicate the call. Rather than make a single-element list with thelistprocedure, build a list consisting of the current match followed by the list of subsequent matches. The procedure to add one element to a list iscons.This isn’t finished: you’ll notice this function always throws an exception. You grind down the list, eventually reach the end… and choke because you aren’t handling the case when the list is empty. I’ll leave this as an exercise.
Now there are other ways to write this function (in fact, better ways, but harder to understand for a beginner). They may or may not be what was intended in your assignment. Imagine you only wanted to have a single recursive call to
find, and noletor any other way to store the result of callingfind. Then you have no choice but to callfind, but with different arguments depending on whether the element was found or not. How can you do this? (Hint: you’ll need a third argument.)