![]() |
Jupyter at Bryn Mawr College |
|
|
Public notebooks: /services/public/dblank / CS245 Programming Languages / 2014-Fall / Notes |
On the first exam, I asked you to write the function list-of
that takes a function $f$, and returns a function that takes a list. The returned function should return #t
if every item in the list has (f item)
as #t
.
It would work like this:
In [1]: ((list-of number?) '(1 2 3 4))
Out [1]: #t
Here is one possible answer:
(define list-of
(lambda (f)
(lambda (ls)
(cond
((null? ls) #t)
((f (car ls)) ((list-of f) (cdr ls)))
(else #f)))))
That is a simple implementation of the definition. But it does recreate the function that takes the list each time it needs it, because the function (list-of f)
doesn't have a name.
Here is a version that uses letrec
(let allowing recursive definitions), so that you only define that function once, and give it a name:
(define list-of
(lambda (f)
(letrec ((list-of-f
(lambda (ls)
(cond
((null? ls) #t)
((not (f (car ls))) #f)
(else (list-of-f (cdr ls)))))))
list-of-f)))
That version is a bit verbose, but also gets the job done.
Finally, here is a version that uses the "named let" construct in Scheme:
(define list-of
(lambda (f)
(lambda (ls)
(let loop ((ls ls))
(cond
((null? ls) #t)
((not (f (car ls))) #f)
(else (loop (cdr ls))))))))
Ah, yes. That is short, and beautiful.
Which do you prefer? Do they all give the same answers? Are there pros and cons to each?